1

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.

5 Answers 5

4

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}
Sign up to request clarification or add additional context in comments.

1 Comment

All the responses are great, but this seems the most "ruby" way to do it. Much thanks for introducing the product method to me.
2
original.flat_map { |k, vs| vs.map { |v| {v => k} } }.reduce(&:merge)

Comments

2

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}

2 Comments

original.each_with_object({}) { |(k, vs), h| vs.each { |v| h[v] = k } } would work.
i was looking to documentation for a suitable method. need to commit to memory those below -))
1

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}}

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.