Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort Ruby Hash by order in array of keys

Tags:

ruby

hash

I have a hash:

sample = { bar: 200, foo: 100, baz: 100 }

How do I sort sample using the order of keys in sort_order:

sort_order = [:foo, :bar, :baz, :qux, :quux]

Expected result:

sample #=> { foo: 100, bar: 200, baz: 100 }

All I can come up with is

new_hash = {}
sort_order.each{|k| new_hash[k] = sample[k] unless sample[k].nil? }
sample = new_hash

There's got to be a better way. Hints?

Keys without values should not be present, i.e. number of keys remain the same, which isn't the case with Sort Hash Keys based on order of same keys in array

like image 943
absessive Avatar asked May 24 '16 05:05

absessive


2 Answers

A functional approach using the intersection of keys:

new_sample = (sort_order & sample.keys).map { |k| [k, sample[k]] }.to_h
#=> {:foo=>100, :bar=>200, :baz=>100}

As @Stefan noted, the abstraction Hash#slice from ActiveSupport's pretty much does the job:

require 'active_support/core_ext/hash'
new_sample = sample.slice(*sort_order)
#=> {:foo=>100, :bar=>200, :baz=>100}
like image 170
tokland Avatar answered Oct 31 '22 23:10

tokland


Please, see my this answer:

sort_order = [:foo, :bar, :baz, :qux, :quux, :corge, :grault,
              :garply, :waldo, :fred, :plugh, :xyzzy, :thud]
sample = { bar: 200, foo: 100, baz: 100 }

sample.sort_by {|k, _| sort_order.index(k)}.to_h
=> {:foo=>100, :bar=>200, :baz=>100}
like image 22
Ilya Avatar answered Nov 01 '22 00:11

Ilya