The code below does this. Note that I used has_key? because you want the output hash to contain all the keys in the input hash, even if their values are nil.
#!/usr/bin/env ruby
def sorted_hash(input_hash, key_sort_order)
new_hash = {}
key_sort_order.each do |key|
if input_hash.has_key?(key)
new_hash[key] = input_hash[key]
end
end
new_hash
end
sort_order = [:foo, :bar, :baz, :qux, :quux]
sample = { bar: 200, foo: 100, baz: 100 }
puts sorted_hash(sample, sort_order)
# Outputs: {:foo=>100, :bar=>200, :baz=>100}
A simplification is to use each_with_object:
def sorted_hash_two(input_hash, key_sort_order)
key_sort_order.each_with_object({}) do |key, result_hash|
if input_hash.has_key?(key)
result_hash[key] = input_hash[key]
end
end
end
puts sorted_hash_two(sample, sort_order)
# Outputs: {:foo=>100, :bar=>200, :baz=>100}
I like @tokland's idea of array intersection (&) better because it elmiinates the need for an if condition:
def sorted_hash_ewo_intersection(input_hash, key_sort_order)
(key_sort_order & input_hash.keys).each_with_object({}) do |key, result_hash|
result_hash[key] = input_hash[key]
end
end # produces: {:foo=>100, :bar=>200, :baz=>100}
sample.sort_by { |k,_| sort_order.index(k) }.to_horsort_order.each_with_object({}) { |sym,h| h[sym] = sample[sym] if sample.key?(sym) }.samplethat do not exist insort_order?