Ruby 将数组的散列合并到散列数组中

Ruby 将数组的散列合并到散列数组中,ruby,Ruby,我有一个数组的散列,比如: {"name": ["John","Jane","Chris","Mary"], "surname": ["Doe","Doe","Smith","Martins"]} 我想把它们合并成一个散列数组,组合相应的元素 结果应该是这样的: [{"name"=>"John", "surname"=>"Doe"}, {"name"=>"Jane", "surname"=>"Doe"}, {"name"=>"Chris", "surname"=&

我有一个数组的散列,比如:

{"name": ["John","Jane","Chris","Mary"], "surname": ["Doe","Doe","Smith","Martins"]}
我想把它们合并成一个散列数组,组合相应的元素

结果应该是这样的:

[{"name"=>"John", "surname"=>"Doe"}, {"name"=>"Jane", "surname"=>"Doe"}, {"name"=>"Chris", "surname"=>"Smith"}, {"name"=>"Mary", "surname"=>"Martins"}] 
你知道如何有效地做到这一点吗


请注意,现实世界的使用场景可能包含数量可变的哈希键。

试试这个

h[:name].zip(h[:surname]).map do |name, surname|
  { 'name' => name, 'surname' => surname }
end
试试这个

h[:name].zip(h[:surname]).map do |name, surname|
  { 'name' => name, 'surname' => surname }
end

我建议编写允许任意数量属性的代码。这并不比假设有两个(
:name
:姓氏
)更困难,但它提供了更大的灵活性,例如,适应未来对属性的数量或命名的更改:

def squish(h)
  keys = h.keys.map(&:to_s)
  h.values.transpose.map { |a| keys.zip(a).to_h }
end

上述示例的步骤如下所示:

b = h.keys
  #=> [:name, :surname, :age] 
keys = b.map(&:to_s)
  #=> ["name", "surname", "age"] 
c = h.values
  #=> [["John", "Jane", "Chris"], ["Doe", "Doe", "Smith"], [22, 34, 96]] 
d = c.transpose
  #=> [["John", "Doe", 22], ["Jane", "Doe", 34], ["Chris", "Smith", 96]] 
d.map { |a| keys.zip(a).to_h }
  #=> [{"name"=>"John", "surname"=>"Doe", "age"=>22},
  #    {"name"=>"Jane", "surname"=>"Doe", "age"=>34},
  #    {"name"=>"Chris", "surname"=>"Smith", "age"=>96}] 
在最后一步中,
b
的第一个值被传递到
map
的块,并为块变量赋值

a = d.first
  #=> ["John", "Doe", 22] 
e = keys.zip(a)
  #=> [["name", "John"], ["surname", "Doe"], ["age", 22]] 
e.to_h
  #=> {"name"=>"John", "surname"=>"Doe", "age"=>22} 

其余的计算是类似的。

我建议编写代码以允许任意数量的属性。这并不比假设有两个(
:name
:姓氏
)更困难,但它提供了更大的灵活性,例如,适应未来对属性的数量或命名的更改:

def squish(h)
  keys = h.keys.map(&:to_s)
  h.values.transpose.map { |a| keys.zip(a).to_h }
end

上述示例的步骤如下所示:

b = h.keys
  #=> [:name, :surname, :age] 
keys = b.map(&:to_s)
  #=> ["name", "surname", "age"] 
c = h.values
  #=> [["John", "Jane", "Chris"], ["Doe", "Doe", "Smith"], [22, 34, 96]] 
d = c.transpose
  #=> [["John", "Doe", 22], ["Jane", "Doe", 34], ["Chris", "Smith", 96]] 
d.map { |a| keys.zip(a).to_h }
  #=> [{"name"=>"John", "surname"=>"Doe", "age"=>22},
  #    {"name"=>"Jane", "surname"=>"Doe", "age"=>34},
  #    {"name"=>"Chris", "surname"=>"Smith", "age"=>96}] 
在最后一步中,
b
的第一个值被传递到
map
的块,并为块变量赋值

a = d.first
  #=> ["John", "Doe", 22] 
e = keys.zip(a)
  #=> [["name", "John"], ["surname", "Doe"], ["age", 22]] 
e.to_h
  #=> {"name"=>"John", "surname"=>"Doe", "age"=>22} 
其余的计算是类似的。

[h[:name],h[:姓氏]]。transpose.map do | name,姓氏|
{'name'=>name,'姓氏'=>姓氏}
结束
[h[:name],h[:姓氏]].transpose.map do | name,姓氏|
{'name'=>name,'姓氏'=>姓氏}
结束

<代码> > p>如果您的数据集非常大,可以考虑使用./p> 这样Ruby就不会在计算过程中创建中间数组

这是可以改进的方法:

h[:名称]
.懒惰
.zip(h[:姓氏])
.map{| name,姓氏{‘name’=>name,‘姓氏’=>name}
.给

<代码> > p>如果您的数据集非常大,可以考虑使用./p> 这样Ruby就不会在计算过程中创建中间数组

这是可以改进的方法:

h[:名称]
.懒惰
.zip(h[:姓氏])
.map{| name,姓氏{‘name’=>name,‘姓氏’=>name}
.给

以下情况下的其他选项:

[…]现实世界的使用场景可能包含一个可变数量的散列键

您可以在一个衬里中使用:

h.values.then { |a, *b| a.zip *b }.map { |e| (h.keys.zip e).to_h }

#=> [{:name=>"John", :surname=>"Doe", :whathever=>1}, {:name=>"Jane", :surname=>"Doe", :whathever=>2}, {:name=>"Chris", :surname=>"Smith", :whathever=>3}, {:name=>"Mary", :surname=>"Martins", :whathever=>4}]

第一部分是这样工作的:

h.values.then { |a, *b| a.zip *b }
#=> [["John", "Doe", 1], ["Jane", "Doe", 2], ["Chris", "Smith", 3], ["Mary", "Martins", 4]]

最后一部分只是映射使用原始键压缩每个元素的元素,然后调用转换为散列

在这里,我删除了调用
。to_h
,以显示中间结果:

h.values.then { |a, *b| a.zip *b }.map { |e| h.keys.zip e }
#=> [[[:name, "John"], [:surname, "Doe"], [:whathever, 1]], [[:name, "Jane"], [:surname, "Doe"], [:whathever, 2]], [[:name, "Chris"], [:surname, "Smith"], [:whathever, 3]], [[:name, "Mary"], [:surname, "Martins"], [:whathever, 4]]]

以下情况下的其他选项:

[…]现实世界的使用场景可能包含一个可变数量的散列键

您可以在一个衬里中使用:

h.values.then { |a, *b| a.zip *b }.map { |e| (h.keys.zip e).to_h }

#=> [{:name=>"John", :surname=>"Doe", :whathever=>1}, {:name=>"Jane", :surname=>"Doe", :whathever=>2}, {:name=>"Chris", :surname=>"Smith", :whathever=>3}, {:name=>"Mary", :surname=>"Martins", :whathever=>4}]

第一部分是这样工作的:

h.values.then { |a, *b| a.zip *b }
#=> [["John", "Doe", 1], ["Jane", "Doe", 2], ["Chris", "Smith", 3], ["Mary", "Martins", 4]]

最后一部分只是映射使用原始键压缩每个元素的元素,然后调用转换为散列

在这里,我删除了调用
。to_h
,以显示中间结果:

h.values.then { |a, *b| a.zip *b }.map { |e| h.keys.zip e }
#=> [[[:name, "John"], [:surname, "Doe"], [:whathever, 1]], [[:name, "Jane"], [:surname, "Doe"], [:whathever, 2]], [[:name, "Chris"], [:surname, "Smith"], [:whathever, 3]], [[:name, "Mary"], [:surname, "Martins"], [:whathever, 4]]]

请不要只发布代码作为答案,还要解释代码的作用以及它是如何解决问题的。带有解释的答案通常质量更高,更像是吸引选票。请不要只发布代码作为答案,还要解释代码的作用以及它如何解决问题。带解释的答案通常质量较高,更像是吸引选票。谢谢。这是迄今为止最好的答案。工作得很漂亮:)谢谢。这是迄今为止最好的答案。作品优美:)