2

The title says it all.

total = {"Bob"=>37, "Alice"=>42, "Carl"=>42}

I want to sort it by value, and then by key, but with the key in descending order.

Like this:

{"Bob"=>37, "Carl"=>42, "Alice"=>42}

I tried:

return total.sort_by { |k, v| [v, k] }

But from here I don't know how to reverse k...

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Mirror318
  • 11,875
  • 14
  • 64
  • 106

3 Answers3

5

Use sort:

total = {"Bob"=>37, "Alice"=>42, "Carl"=>42}
total.sort { |(k1, v1), (k2, v2)| [v1, k2] <=> [v2, k1] }.to_h
# => {"Bob"=>37, "Carl"=>42, "Alice"=>42}

First, sort by values (v1 <=> v2) and then reverse sort by keys (k2 <=> k1), and since we need it simultaneously, put it into array.

EDIT: @Mirror318, it just looks scary, take a look at the excellent explanation here: What is the Ruby <=> (spaceship) operator?

Community
  • 1
  • 1
Alexey Shein
  • 7,342
  • 1
  • 25
  • 38
3

Another way:

total.sort_by { |k,v| [-v,k] }.reverse.to_h
  #=> {"Bob"=>37, "Carl"=>42, "Alice"=>42}
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
-1

If you're using ruby >= 2.1, then just call to_h on sorted array of tuples:

total = {"Bob"=>37, "Alice"=>42, "Carl"=>42}
total.sort_by{|k, v| [v, k]}.to_h

Else call Hash.new:

total = {"Bob"=>37, "Alice"=>42, "Carl"=>42}
Hash.new total.sort_by{|k, v| [v, k]}.to_h
Aetherus
  • 8,720
  • 1
  • 22
  • 36