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
  • 115,525
  • 42
  • 225
  • 281
Mirror318
  • 10,810
  • 11
  • 57
  • 93

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,054
  • 1
  • 22
  • 36
3

Another way:

total.sort_by { |k,v| [-v,k] }.reverse.to_h
  #=> {"Bob"=>37, "Carl"=>42, "Alice"=>42}
Cary Swoveland
  • 101,330
  • 6
  • 60
  • 95
-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,234
  • 22
  • 35