21

So I've built a custom array of users like such:

[["user1",432],["user1",53],["user9",58],["user5",75],["user3",62]]

I want to sort them by the 2n'd value in each array, from largest to smallest. I have a feeling using sort or sort_by for arrays is the way to do this, but I'm not really sure how to accomplish it

3 Answers 3

46

sort_by

If you're interested in sort_by, you could destructure your inner arrays

array.sort_by { |_, x| x }.reverse

or call the index operator

array.sort_by { |x| x[1] }.reverse

Instead of reversing you could negate values returned from the block.

array.sort_by { |_, x| -x }
array.sort_by { |x| -x[1] }

Yet another alternative would be to use an ampersand and Array#last.

array.sort_by(&:last).reverse

sort

A solution using sort could be

array.sort { |x, y| y[1] <=> x[1] }
Sign up to request clarification or add additional context in comments.

4 Comments

If you're going for completeness then you might want to include array.sort_by(&:last).reverse.
and yet for completeness you should add the simple array.sort_by { |u, uid| -uid }. Also, note that it could benefit from using Enumerable#reverse_each for a more space-efficient reversing (when a enumerator fits, of course).
I am facing issues while using sort or sort_by in my presenter and controller. It says undefined method 'sort_by' . Can any one shed light on this?
sorry this question is not related, can you explain how your first and second solution works, thanks
2

use this: array.sort_by { |a| -a[1] }

2 Comments

I've been always puzzle by sort_by not having a reverse option.
nit-picking: unpacking block arguments is considered more idiomatic that accessing them as an array.
0

One more solution to sort_by in reverse (- doesn't work in all cases, think sorting by string):

class Invertible
  include Comparable
  attr_reader :x

  def initialize(x)
    @x = x
  end

  def <=> (x)
    x.x <=> @x
  end
end

class Object
  def invertible
    Invertible.new(self)
  end
end

[1, 2, 3].sort_by(&:invertible) #=> [3, 2, 1]
["a", "b", "c"].sort_by(&:invertible) #=> ["c", "b", "a"]

It is slower than reverse in simple case, but may work better with complex sorts:

objs.sort_by do |obj|  
  [obj.name, obj.date.invertible, obj.score, ...]
end

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.