Say I have a hash like:
foo = {
:bar => ['r', 'baz'], # has a total str length of 4 characters inside of the array
:baz => ['words', 'etc', 'long words'] # has a total str length of 18 characters inside of the array,
:blah => ['at'] # has a total str length of 2 characters inside of the array
# etc...
}
How would I go about sorting this hash by the total string length of the items contained within the arrays? The resulting hash order in this case should be: :blah, :bar, :baz
I'd just do this:
Hash[foo.sort_by { |k, v| v.join.length }]
I assume you're not intending the change the original Hash values, just re-order them.
Traditionally, hashes are not ordered, and therefore not sortable. Ruby 1.9 hashes are ordered, but the language provides no easy way to re-order the elements. Just like in 1.8, sorting a hash returns an array of pairs:
{ c:3, a:1, b:2 }.sort => [ [:a,1], [:b,2], [:c,3] ]
(Actually, 1.8 would blow up on that because symbols aren't comparable in 1.8, but never mind.)
But as long as you're OK with the list of pairs, you can sort a hash (or an array) by anything you like. Just use sort_by and pass a block that extracts the sort key, or use sort with a block that does the comparison:
foo.sort_by { |key, strings| strings.join.length }
or, if you want the longest ones first:
foo.sort_by { |key, strings| -strings.join.length }
Then, if you're using 1.9 and want to turn the result back into a Hash, you can do so thus (thanks, Jörg W Mittag):
Hash[ foo.sort_by { |key, strings| strings.join.length } ]
...which is the same answer as d11wtq.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With