HashKeyOrderable
っていうものを作りました。http://gist.github.com/358709
作った動機
Hashをeachで繰り返すときにキーで順序を指定したい、というのはたまにありますが、出力したい順序が決まっている場合もある。
例えば、赤、青、黄色という順番で出力したいとか。
colors = {:red => 1, :blue => 2, :yellow => 4} #=> {:blue=>2, :yellow=>4, :red=>1} colors.each{|k,v| puts "#stdout #{k.inspect}: #{v.inspect}"} #stdout :blue: 2 #stdout :yellow: 4 #stdout :red: 1
これを
#stdout :red: 1 #stdout :blue: 2 #stdout :yellow: 4
という順に出力させたい。
使い方
http://gist.github.com/358709
の内容をhash_key_orderable.rb とかいう名前にして、使用したい箇所でrequireする。で、対象のHashにHashKeyOrderableをextendさせて、key_order=メソッドで出力したい順番を指定すればOK。
colors.extend(HashKeyOrderable) #=> {:blue=>2, :yellow=>4, :red=>1} colors.key_order = [:red, :blue, :yellow] #=> [:red, :blue, :yellow] colors.each{|k,v| puts "#stdout #{k.inspect}: #{v.inspect}"} #stdout :red: 1 #stdout :blue: 2 #stdout :yellow: 4
特徴
key_orderに指定していないキーがHashに含まれている場合は、key_orderで指定されたものよりも後にブロックに渡される。また、inspectも拡張するのでとても読みやすいはず。
rainbow = {:red => 1, :orange => 2, :yellow => 4, :green => 8, :blue => 16, :navy => 32, :purple => 64} #=> {:navy=>32, :blue=>16, :purple=>64, :yellow=>4, :orange=>2, :green=>8, :red=>1} rainbow.extend(HashKeyOrderable) #=> {:navy=>32, :blue=>16, :purple=>64, :yellow=>4, :orange=>2, :green=>8, :red=>1} rainbow.key_order = [:red, :blue, :yellow] #=> [:red, :blue, :yellow] puts rainbow.inspect {:red=>1, :blue=>16, :yellow=>4, :navy=>32, :purple=>64, :orange=>2, :green=>8} #=> nil
逆にkey_order=で指定されているが、Hashには含まれていないキーの場合は単純に無視されます。
rainbow.key_order = [:red, :blue, :yellow, :black] #=> [:red, :blue, :yellow, :black] puts rainbow.inspect {:red=>1, :blue=>16, :yellow=>4, :navy=>32, :purple=>64, :orange=>2, :green=>8} #=> nil