katericata
katericata

Reputation: 1058

How to sort a hash by the values of another array in Ruby?

Looks like a piece of cake, but can't solve it..

elements = ['one', 'two', 'three']

sort_me = {'three': 3, 'two': 2, 'one': 1}

sort_me.sort_by { |k, _| elements.index k }.to_h does not sort it the way it should. The hash stays the same.

The desired output is {:one=>1, :two=>2, :three=>3}.

Upvotes: 3

Views: 1511

Answers (2)

Eric Duminil
Eric Duminil

Reputation: 54223

You don't need to sort anything, and you also don't need to create a lookup table. Your array is already sorted the way you want and your sort_me hash is already a lookup table:

elements = ['one', 'two', 'three']
# => ["one", "two", "three"]
sort_me = {'three' => 3, 'two' => 2, 'one' => 1}
# => {"three"=>3, "two"=>2, "one"=>1}
elements.map{|key| [key, sort_me[key] ] }.to_h
# => {"one"=>1, "two"=>2, "three"=>3}

If you want to use symbols and strings:

elements = ['one', 'two', 'three']
# => ["one", "two", "three"]
sort_me = {three: 3, two: 2, one: 1}
# => {:three=>3, :two=>2, :one=>1}
elements.map{|key| [key.to_sym, sort_me[key.to_sym] ] }.to_h
# => {:one=>1, :two=>2, :three=>3}

Finally, if some elements are not used in the hash, you could simply remove pairs with nil values:

elements = ['one', 'two', 'two_and_a_half', 'three']
# => ["one", "two", "two_and_a_half", "three"]
elements.map{|key| [key.to_sym, sort_me[key.to_sym] ] }.to_h
# => {:one=>1, :two=>2, :two_and_a_half=>nil, :three=>3}
elements.map{|key| [key.to_sym, sort_me[key.to_sym] ] }.reject{|k, v| v.nil? }.to_h
# => {:one=>1, :two=>2, :three=>3} 

Upvotes: 3

katericata
katericata

Reputation: 1058

Oh Gosh.. I am creating a hash of symbol keys and I want to sort it with an array of strings. Looks like my Python background tricked me here.

sort_me = {'three': 3, 'two': 2, 'one': 1} results to => {:three=>3, :two=>2, :one=>1}

Let's convert the hash key into string to get the sorting work:

sort_me.sort_by { |k,_| elements.index k.to_s }.to_h

Upvotes: 2

Related Questions