Reputation: 139
I know that there must be some simple and elegant way to do this, but I'm drawing a blank.
I have a table (or group of key value pairs)
id,val
64664,68
64665,65
64666,53
64667,68
64668,6
64668,27
64668,33
64669,12
In most cases there is one value per id. In some cases there are multiples. I want to end up with each id with multiple values represented as an array of those values
something like this:
[ 64664 => 68,
64665 => 65,
64666 => 53,
64668 =>[6,27,33],
64669 => 12
]
Any brilliant ideas?
Upvotes: 0
Views: 1118
Reputation: 80085
values = [
[64664, 68],
[64665, 65],
[64666, 53],
[64667, 68],
[64668, 6],
[64668, 27],
[64668, 33],
[64669, 12],
]
# When key not present, create new empty array as default value
h = Hash.new{|h,k,v| h[k]=[]}
values.each{|(k,v)| h[k] << v}
p h #=>{64664=>[68], 64665=>[65], 64666=>[53], 64667=>[68], 64668=>[6, 27, 33], 64669=>[12]}
Upvotes: 0
Reputation: 369424
You can use Hash#merge
to merge two hashes. Using Enumerable#inject
, you can get what you want.
tbl = [
[64664, 68],
[64665, 65],
[64666, 53],
[64667, 68],
[64668, 6],
[64668, 27],
[64668, 33],
[64669, 12],
]
# Convert the table to array of hashes
hashes = tbl.map { |id, val|
{id => val}
}
# Merge the hashes
hashes.inject { |h1, h2|
h1.merge(h2) { |key,old,new|
(old.is_a?(Array) ? old : [old]) << new
}
}
# => {64664=>68, 64665=>65, 64666=>53, 64667=>68, 64668=>[6, 27, 33], 64669=>12}
Upvotes: 3