user1553220
user1553220

Reputation: 139

Convert Table to Multidimensional Hash in Ruby

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

Answers (2)

steenslag
steenslag

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

falsetru
falsetru

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

Related Questions