freddiefujiwara
freddiefujiwara

Reputation: 59029

array x array matrix in ruby

I'd like to convert from

{'key1' => (1..10) ,
 'key2' => (11..20) , 
'key3' => (21..30)}

to

[{'key1' => 1, 'key2' => 11, 'key3' => 21},
{'key1' => 1, 'key2' => 11, 'key3' => 22},...
 .
 .
{'key1' => 10, 'key2' => 20, 'key3' => 30}]

How to solve it?

Upvotes: 3

Views: 260

Answers (6)

Boris Stitnicky
Boris Stitnicky

Reputation: 12578

Lazier way of doing the same:

h = {
  'key1' => (1..10),
  'key2' => (11..20),
  'key3' => (21..30)
}

result = ( 0...h.values.map( &:to_a ).map( &:size ).max ).map do |i|
  Hash.new { |hsh, k| hsh[k] = h[k].to_a[i] }
end

result[1]['key3'] #=> 22

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110665

h = {'key1' => (1..10), 'key2' => (11..20), 'key3' => (21..30)}

Edit 1: made some changes, principally the use of inject({}):

f,*r = h.map {|k,v| [k].product(v.to_a)}
f.zip(*r).map {|e| e.inject({}) {|h,a| h[a.first] = a.last; h}}

Edit 2: After seeing the use of Hash[] in @Phrogz's answer to another question:

f,*r = h.map {|k,v| [k].product(v.to_a)}
f.zip(*r).map {|e| Hash[*e.flatten]}

Upvotes: 1

Stefan
Stefan

Reputation: 114138

h = {
  'key1' => (1..10),
  'key2' => (11..20),
  'key3' => (21..30)
}

h.map { |k,v| [k].product(v.to_a) }.transpose.map { |e| Hash[e] }
#=> [{"key1"=>1, "key2"=>11, "key3"=>21},
#    {"key1"=>2, "key2"=>12, "key3"=>22},
#    {"key1"=>3, "key2"=>13, "key3"=>23},
#    {"key1"=>4, "key2"=>14, "key3"=>24},
#    {"key1"=>5, "key2"=>15, "key3"=>25},
#    {"key1"=>6, "key2"=>16, "key3"=>26},
#    {"key1"=>7, "key2"=>17, "key3"=>27},
#    {"key1"=>8, "key2"=>18, "key3"=>28},
#    {"key1"=>9, "key2"=>19, "key3"=>29},
#    {"key1"=>10, "key2"=>20, "key3"=>30}]

Upvotes: 2

Cary Swoveland
Cary Swoveland

Reputation: 110665

So many ways... A kiss answer (edited to extend to any number of keys):

s = {'key1' => (1..10), 'key2' => (11..20), 'key3' => (21..30)}
r = []
s.each {|k,v| a = []; (v.to_a).each {|i| a << {k=>i}}; r << a}
result = r.shift
r.each {|e| result = result.product(e).map(&:flatten)}
result

Upvotes: 2

Arup Rakshit
Arup Rakshit

Reputation: 118261

Here it is :

hsh = {'key1' => (1..10) ,'key2' => (11..20) , 'key3' => (21..30)}
keys = hsh.keys
hsh['key1'].to_a.product(hsh['key2'].to_a,hsh['key3'].to_a).map{|a|Hash[keys.zip(a)]}

# => [{'key1' => 1, 'key2' => 11, 'key3' => 21},
#   {'key1' => 1, 'key2' => 11, 'key3' => 22},...
#   .
#   .
#   {'key1' => 10, 'key2' => 20, 'key3' => 30}]

You could also write the above as below,when you have more number of keys:

hsh = {'key1' => (1..10) ,'key2' => (11..20) , 'key3' => (21..30)}
keys = hsh.keys
array = hsh.values_at(*keys[1..-1]).map(&:to_a)
hsh['key1'].to_a.product(*array).map{|a|Hash[keys.zip(a)]}

Upvotes: 4

steenslag
steenslag

Reputation: 80065

h = {'key1' => (1..10) ,
'key2' => (11..20) , 
'key3' => (21..30)}

arrays = h.values.map(&:to_a).transpose
p arrays.map{|ar| Hash[h.keys.zip(ar)] }
#=> [{"key1"=>1, "key2"=>11, "key3"=>21}, {"key1"=>2, "key2"=>12, "key3"=>22},...

Upvotes: 1

Related Questions