Is there a more elegant solution than `sortperm(sortperm(...))`

Say I have two vectors of identifiers - the second one being a shuffled version of the first one - like this:

using Random, Test
a = [ randstring(5) for _ in 1:20 ]
b = shuffle(a)

and now I want to loop through a such that the elements occur in the order given by b, i.e. I need a permutation v such that a[v] == b.

The solution I came up with is:

v = sortperm(a)[sortperm(sortperm(b))]
@test a[v] == b

Is there a more elegant than the above solution?

I do not care about performance right now - but I could imagine that the sortperm(sortperm(.)) construct will not behave well for longer vectors - so there might be also a more performant solution.

I am curious about your original problem. Why do you do it like this, if I may ask?

Given your question, Iā€™d suggest to simply loop over b (with different starting indices).

I am asking to avoid an XY-Problem

1 Like

OK - a is intact not just a vector of identifiers but a vector of structs - the identifier is just one field in this struct. The order I want to go through them is given by a vector b of just these identifiers. The order is computed from data which is not presented in a, therefore I cannot just do a sort!(a, ...).

So therefore I need this permutation v and can for instance:

for k in 1:length(b)
  do_something_with(a[v[k]])
end

in the order given by b.

v = indexin(b, a)

but why not write your loop as

for v in b
    do_something_with(a[v])
end

?

3 Likes

This is exactly what I was looking for. Thanks

The permutation v = indexin(b, a) is the one I am looking for. The loop should probably be:

for k in v
  do_something_with(a[k])
end

Yes, my bad.
I was thinking of a as a Dict, which might be worth considering if you are doing many indexing-using-identifiers operations.