Given a key (in the sense of /.), I'd like to obtain the rank (the i.~\:~ kind, not the " kind) of each item within the collection corresponding to its key. My first instinct was to try (i.~\:~)/. but this is not exactly what I want.
In the following example, collection 0 is 10 30 20 20 and has ranks 3 0 1 1, while collection 1 is 200 100 300 and has ranks 1 2 0. The problem is the extra 0 appended to make them the same size, and the rearranging that happens. I want the output to be 3 1 2 0 0 1 1, so that it corresponds to the original right-side input. 0 1 1 1 0 0 0 (i.~\:~)/. 10 200 100 300 30 20 20 3 0 1 1 1 2 0 0 I found that the following expression works. rankbykey=: +/@( =...@[ ( [ * (i.~\:~"_1)@:( (*"_1 _))) ] ) For example: 0 1 1 1 0 0 0 rankbykey 10 200 100 300 30 20 20 3 1 2 0 0 1 1 (1 1,1 0,:1 0) rankbykey 0 0,0 1,:0 2 0 1 0 However, rankbykey runs out of memory when I apply it to huge arrays (15M rows, 7 cols). So then I found the following solution, which works better on huge arrays. rankbykey2=: ( ;@((i.~\:~)&.>@</.) /: ;@([</....@#@]) ) This seems needlessly messy because of the boxing, and I imagine others have run into the same question, although I haven't been able to find anything in phrases or the the wiki. It looks like something J should do easily, but I am no J expert. Does anyone know a better solution that will work on large arrays? Thanks, Jordan ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
