(2&{./. i.@#) 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8
0 9
1 3
2 0
4 8
5 12
6 16
7 0
11 18
13 0
0 {"1 original will select the unique values, and if
1 {"1 original
is 0, there was only 1 copy of it.
Henry Rich
On 6/12/2014 1:17 PM, Marshall Lochbaum wrote:
I came across this problem and was wondering if anyone could come up
with a solution that is both elegant and fast:
Given a list of positive integers, return a mask (or index list) which
selects the first two of each unique value in the list.
Of course ~: is the solution if you only want the first value. A fast
but ugly solution using ~: is
f1 =. (] +. ~:@:(*-.)) ~:
which relies on the fact that the list is always positive. A more
general solution using key, which returns an unordered list of indices,
is
f2 =. (2&{.)^:(2<#)(<@)/.(;@:) i.@#
which isn't exactly pretty, but at least allows you to change the number
of values you want. It's also much slower than f1:
d =. 99 , 100 + 1e7?.@$10000
(I.@:f1 -: /:~@:f2) d
1
6!:2 'f1 d'
0.273576
6!:2 'f2 d'
1.08829
Any other ideas?
Marshall
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm