程式扎記: [ 文章收集 ] How to Sort a Hash in Ruby

標籤

2014年10月22日 星期三

[ 文章收集 ] How to Sort a Hash in Ruby

Source From Here 
Preface 
Let's say you have the following hash of people to ages: 
>> people = {:john=>23, :ken=>18, :peter=>54}
=> {:john=>23, :ken=>18, :peter=>54}

Now, what if we want to "sort" the hash into age order? We can't. At least, not exactly. Hashes are not meant to be in a certain order (though they are in Ruby 1.9) as they're a data structure where one thing merely relates to another thing. The relationships themselves are not elements of data in themselves. 

We can, however, build other data structures that represent sorted versions of the data within a hash. An Array, for example: 
# Let's say we want to get a list of the ages in order:
>> people.values.sort
=> [18, 23, 54]

This gives us the values but you might want to have both the values and their associated keys in a particular order. 

Enumerable To The Rescue! 
Luckily, Hash has the Enumerable module mixed in which provides us with methods like sort and sort_by. Let's give them a go: 
>> people[:alice]=31
=> 31
>> people
=> {:john=>23, :ken=>18, :peter=>54, :alice=>31}
>> people.sort # default will sorting with key of hash map
=> [[:alice, 31], [:john, 23], [:ken, 18], [:peter, 54]]

Next, let's use sort_by to get where we want to go (sorting by age): 
>> people.sort_by{|name, age| age}
=> [[:ken, 18], [:john, 23], [:alice, 31], [:peter, 54]]
>> people.sort_by{|name, age| age}.reverse # sorting by age in descending way
=> [[:peter, 54], [:alice, 31], [:john, 23], [:ken, 18]]

In this situation we're using sort_by to sort by a specific collection - the values (ages, in our case). Since integers (FixNum objects, in this case) can be compared with <=>, we're good to go. We get a nested array back with one element per hash element in order to preserve the 'ordering'. You can then use Array or other Enumerable methods to work with the result (tip: each* is a good place to start!

A More Complex Situation 
Let's make our hash more complex: 
>> people = {:fred=>{:name=>"Fred", :age=>23}, :joan=>{:name=>"Joan", :age=>18}, :pete=>{:name=>"Pete", :age=>54}}
=> {:fred=>{:name=>"Fred", :age=>23}, :joan=>{:name=>"Joan", :age=>18}, :pete=>{:name=>"Pete", :age=>54}}

This time we not only have a hash - we have a hash filled with other hashes. What if we want to sort by values within the nested hashes? It's much the same as before, except we address the inner hash during the sort: 
>> people.sort_by{|k, v| v[:age]}
=> [[:joan, {:name=>"Joan", :age=>18}], [:fred, {:name=>"Fred", :age=>23}], [:pete, {:name=>"Pete", :age=>54}]]

Supplement 
Basic : 內建型態與操作 - 雜湊型態 
Basic : 內建型態與操作 - 陣列型態

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!