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 `struct`s - 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
``````

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