Merge two arrays into a hash

I have two arrays:

members = ["Matt Anderson", "Justin Biltonen", "Jordan Luff", "Jeremy London"] instruments = ["guitar, vocals", "guitar", "bass", "drums"] 

What I would like to do is to combine them so that the resulting data structure is a hash, for example:

 {"Matt Anderson"=>["guitar", "vocals"], "Justin Biltonen"=>"guitar", "Jordan Luff"=>"bass", "Jeremy London"=>"drums"} 

Note that the value for "Matt Anderson" is now an array instead of a string. Any Ruby wizards can do this?

I know that Hash[*members.zip(instruments).flatten] combines them almost the way I want, but what about first including the string β€œguitars, vocals” in the array? Thank.

+49
ruby
Mar 02 '11 at 23:40
source share
7 answers

Use map and split to convert tool strings to arrays:

 instruments.map {|i| i.include?(',') ? (i.split /, /) : i} 

Then use Hash[] and zip to combine members with instruments :

 Hash[members.zip(instruments.map {|i| i.include?(',') ? (i.split /, /) : i})] 

To obtain

 {"Jeremy London"=>"drums", "Matt Anderson"=>["guitar", "vocals"], "Jordan Luff"=>"bass", "Justin Biltonen"=>"guitar"} 

If you don't care if the lists of individual elements are also arrays, you can use this simpler solution:

 Hash[members.zip(instruments.map {|i| i.split /, /})] 

which gives you the following:

 {"Jeremy London"=>["drums"], "Matt Anderson"=>["guitar", "vocals"], "Jordan Luff"=>["bass"], "Justin Biltonen"=>["guitar"]} 
+43
Mar 02 2018-11-11T00:
source share

As Rafe Kettler said, using zip is the way to go.

 Hash[members.zip(instruments)] 
+85
Feb 04 2018-12-12T00:
source share

Example 01

 k = ['a', 'b', 'c'] v = ['aa', 'bb'] h = {} k.zip(v) { |a,b| h[a.to_sym] = b } # => nil ph # => {:a=>"aa", :b=>"bb", :c=>nil} 

Example 02

 k = ['a', 'b', 'c'] v = ['aa', 'bb', ['aaa','bbb']] h = {} k.zip(v) { |a,b| h[a.to_sym] = b } ph # => {:a=>"aa", :b=>"bb", :c=>["aaa", "bbb"]} 
+7
12 Oct '12 at 3:01
source share

This is the best and cleanest way to do what you want.

 Hash[members.zip(instruments.map{|i| i.include?(',') ? i.split(',') : i})] 

Enjoy it!

+3
Aug 19 '14 at 23:22
source share
 h = {} members.each_with_index do |el,ix| h[el] = instruments[ix].include?(",") ? instruments[ix].split(",").to_a : instruments[ix] end h 
+1
Mar 02 2018-11-11T00:
source share
 members.inject({}) { |m, e| t = instruments.delete_at(0).split(','); m[e] = t.size > 1 ? t : t[0]; m } 

If you don't care about 1-element arrays as a result, you can use:

 members.inject({}) { |m, e| m[e] = instruments.delete_at(0).split(','); m } 
+1
Mar 03 2018-11-11T00:
source share
 h = {} members.each_with_index {|item, index| h.store(item,instruments[index].split) } 
0
Mar 02 2018-11-23T00:
source share



All Articles