4

This seems like its fairly simple, and should have been asked before, but everything I find on Stack Overflow doesn't seem to work. I have an array of 4 objects, and I'd like to re-order it in a particular order. So, it looks like this:

array = [Obj1, Obj2, Obj3, Obj4]

I have another array of integers which represent the desired order of the indices:

desired_order = [2,3,0,1]

So what I would like to see after ordering array properly is:

array = [Obj3, Obj4, Obj1, Obj2]

I've already figured sort_by is the method to use, but I can't seem to come up with the proper syntax. Any help is greatly appreciated!

4
  • possible duplicate of How to sort an array in Ruby to a particular order? Commented Dec 14, 2012 at 0:59
  • @theTinMan. Doesn't seem the same problem, here you already have the indexes. Commented Dec 14, 2012 at 8:08
  • I don't know what your task is, but it looks like array.rotate.rotate could help in this case. Maybe also in other cases? :-P Commented Dec 14, 2012 at 11:34
  • Yeah, this was an incredibly rare edge-case on dealing with an out of date CMS. I have no ability to alter how the data was entered, and it has to be rendered in a particular order. Only this one particular item in the entire system is in the wrong order... =\ Commented Dec 14, 2012 at 22:54

3 Answers 3

7

Array#values_at does exactly what you need:

array.values_at(*desired_order)
Sign up to request clarification or add additional context in comments.

5 Comments

Any idea how this compares benchmark-wise to map? In this case it won't matter since I only have 4 items, but for future generations' sake...
Why a map would be better with more elements? it's exactly the same operation, only that the abstraction already exists in the core (and probably implemented in C)
Wasn't claiming it was, I was asking the question..Didn't know this is using the same operation as map.
Yeah, I know, the thing is I don't understand why you are asking. Imagine that you have a million elements to retrieve, you still have an array of a million elements to map, don't you? so there is no difference conceptually. However, since the map is done at Ruby level, and values_at at C level, values_at should be faster. You can do the benchmarking but I'd very surprised if that's not the case.
Could you edit this a bit? Looks like values_at requires a comma separated list of integers, whereas desired_order in my above question is an array of integers, so as written with my code above this would throw an error.
5
desired_order.map{|i| array[i]}

3 Comments

Ah ha! Thank you both, guess sort_by was not the correct method after all :)
You can also do it with sort_by, but it is not as straightforward: array.sort_by.with_index{|_, i| desired_order.index(i)} and is much less efficient.
@Tokland's values_at is better.
1

If you have indexes already, then you can just map them to objects:

array = %w[obj1 obj2 obj3 obj4]
desired_order = [2,3,0,1]

desired_order.map{|idx| array[idx]} # => ["obj3", "obj4", "obj1", "obj2"]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.