0

I have an array

array_a1 = [9,43,3,6,7,0]

which I'm trying to get the sort indices out of, i.e. the answer should be

array_ordered = [6, 3, 4, 5, 1, 2]

I want to do this as a function, so that

def order (array)

will return array_ordered

I have tried implementing advice from Find the index by current sort order of an array in ruby but I don't see how I can do what they did for an array :(

if there are identical values in the array, e.g.

array_a1 = [9,43,3,6,7,7]

then the result should look like:

array_ordered = [3, 4, 5, 6, 1, 2]

(all indices should be 0-based, but these are 1-based)

5
  • What if there's duplicate values? Commented Sep 4, 2019 at 20:58
  • Hint: A crappy but effective way is to sort the array, then use index to find out where each one went. You can do that with map. A better way is to convert that into pairs, then remap back. Commented Sep 4, 2019 at 20:59
  • 1
    @tadman I've edited the question to show how it should look if there are identical values (equivalent of R's order) how can I do what you're saying? I am a newb with Ruby Commented Sep 4, 2019 at 21:02
  • You have made the question unnecessarily complex when you show the desired return values as arrays of 1-based indices and then say, "all indices should be 0-based, but these are 1-based". Unless otherwise stated, indices are zero-based, show just show the desired return values as arrays of (zero-based) indices and say nothing about the index base. Commented Sep 4, 2019 at 22:10
  • After an answer was posted you changed the question. Yes, you must deal with the possibility of duplicate values, but by giving a tie-breaking rule you made some answers incorrect, including the one to which you awarded the checkmark. Another possibility would be to say that the array contains no duplicate values--which at least would do no harm--and then post a separate, similar question that permits duplicate values and gives a rule for breaking ties. In any event, never change the question after an answer has been posted. Lastly, when you edit there's no need to write "Edit". Commented Sep 4, 2019 at 22:15

3 Answers 3

5

You can do it this way:

[9,43,3,6,7,0].
  each_with_index.to_a. # [[9, 0], [43, 1], [3, 2], [6, 3], [7, 4], [0, 5]]
  sort_by(&:first).     # [[0, 5], [3, 2], [6, 3], [7, 4], [9, 0], [43, 1]]
  map(&:last)           
#=> [5, 2, 3, 4, 0, 1]

First you add index to each element, then you sort by the element and finally you pick just indices.

Note, that array are zero-indexed in Ruby, so the results is less by one comparing to your spec.

Sign up to request clarification or add additional context in comments.

1 Comment

Another map could fix that with a +1, but this is what I came up with too.
2

You should be able to just map over the sorted array and lookup the index of that number in the original array.

arr = [9,43,3,6,7,0]
arr.sort.map { |n| arr.index(n) } #=> [5, 2, 3, 4, 0, 1]

Or if you really want it 1 indexed, instead of zero indexed, for some reason:

arr.sort.map { |n| arr.index(n) + 1 } #=> [6, 3, 4, 5, 1, 2]

1 Comment

This is terribly inefficient as index must step through arr for each element of the sorted array. I see @tadman pointed that out in a comment on the question.
1
array_a1 = [9,43,3,6,7,0]

array_a1.each_index.sort_by { |i| array_a1[i] }
  #=> [5, 2, 3, 4, 0, 1]

If array_a1 may contain duplicates and ties are to be broken by the indices of the elements (the element with the smaller index first), you may modify the calculation as follows.

[9,43,3,6,7,7].each_index.sort_by { |i| [array_a1[i], i] }
  #=> [2, 3, 4, 5, 0, 1]

Enumerable#sort_by compares two elements with the spaceship operator, <=>. Here, as pairs of arrays are being compared, it is the method Array#<=> that is used. See especially the third paragraph of that doc.

1 Comment

I've said nothing about one-based indices as it seems clear that zero-based indices are wanted.

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.