stevensonmt
stevensonmt

Reputation: 732

Ruby Hash Values is Array, need to convert to string

I have a hash of integers as keys and arrays of strings as values. I need to convert this to a new hash that inverts this relationship with each item from the array of strings in the original hash values becoming a key in the new hash and each original key becoming the associated value. For example:

original = {1 => ['a', 'b', 'c'], 2 => ['g', 'm', 'z']}

new_hash = {'a' => 1, 'b' => 1, 'c' => 1, 'g' => 2, 'm' => 2, 'z' => 2}

I'm struggling to extract the items from the original array values. It's easy enough to do

original.each { |k, v| new_hash[v] = k }

but this keeps the original array as the new key. I've tried doing something like

original.each { |k, v| new_hash[v.each { |i| i }] = k }

but this also returns the original array for some reason.

Upvotes: 1

Views: 1459

Answers (5)

Stefan
Stefan

Reputation: 114138

Another one, via Array#product:

original.flat_map { |k, v| v.product([k]) }.to_h
#=> {"a"=>1, "b"=>1, "c"=>1, "g"=>2, "m"=>2, "z"=>2}

Upvotes: 4

marmeladze
marmeladze

Reputation: 6564

the below snippet will give what you want, but let me think on a more readable and elegant solution.

newhash = {}

original.each do |k,v|
  v.each do |v2|
    newhash[v2] = k
  end
end
#=> {1=>["a", "b", "c"], 2=>["g", "m", "z"]}

newhash
#=> {"a"=>1, "b"=>1, "c"=>1, "g"=>2, "m"=>2, "z"=>2}

Upvotes: 2

Alexandre Abreu
Alexandre Abreu

Reputation: 1417

original.map { |number, ary| Hash[ary.map { |char| [char, number] }] }.reduce(&:merge)

Upvotes: 1

opearo
opearo

Reputation: 11

Your approach is close. You'll have to iterate each element in the values array when assigning the new key/value pair to the newHash

newHash = {}
original.each { |k, v| v.each {|i| newHash[i] = k}}

Upvotes: 1

ndnenkov
ndnenkov

Reputation: 36101

original.flat_map { |k, vs| vs.map { |v| {v => k} } }.reduce(&:merge)

Upvotes: 2

Related Questions