-1

I have an array of points:

arr = [[2,0], [1,0], [2,1], [1,1]]

How would I sort the elements in descending and ascending orders by x first and then by y values of the similar x value?

max = [[2,1], [2,0], [1,1], [1,0]]
min = [[1,0], [1,1], [2,0], [2,1]]

.

sawa
  • 165,429
  • 45
  • 277
  • 381
Chris
  • 391
  • 4
  • 14

2 Answers2

3
min = arr.sort
# => [[1, 0], [1, 1], [2, 0], [2, 1]]
max = min.reverse
# => [[2, 1], [2, 0], [1, 1], [1, 0]]

If performance is an issue rather than simplicity, then the following can be used.

min = arr.sort_by(&:itself)
sawa
  • 165,429
  • 45
  • 277
  • 381
  • [Benchmarks](http://stackoverflow.com/questions/2642182/sorting-an-array-in-descending-order-in-ruby/2651028#2651028) show that sorting then using `reverse` is faster than using a negated value so +1. – the Tin Man Aug 24 '15 at 02:57
  • In v2.2+ you can use [Array#max](http://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-max) to get `max`: `arr.max(arr.size) #=> [[2, 1], [2, 0], [1, 1], [1, 0]]` – Cary Swoveland Aug 24 '15 at 05:12
  • @CarySwoveland Is the order guaranteed in any document? – sawa Aug 24 '15 at 05:32
  • I was wondering about that too. Though I haven't seen anything, I'd expect it to duplicate `sort.reverse`. A small experiment: `n=10**6; a = (0..n).to_a.reverse; puts a.shuffle.max(a.size) == a #=> true`. Similar for `min`, `min_by` and `max_by`. – Cary Swoveland Aug 24 '15 at 06:29
1

This is a good use case for Enumerable#sort_by.

For max:

arr.sort_by { |el| [-el[0], -el[1]] }
=> [[2, 1], [2, 0], [1, 1], [1, 0]]

For min:

arr.sort_by { |el| [el[0], el[1]] }
=> [[1, 0], [1, 1], [2, 0], [2, 1]]
Anthony
  • 15,435
  • 4
  • 39
  • 69