我有以下数组:
myarray = [
['usa','primary', 'john'],
['france','primary', 'lira'],
['usa', 'secondary', 'steve'],
['germany', 'primary', 'jeff'],
['france', 'secondary', 'ben']
]
我想将其转换为哈希数组,如:
[
{:country => 'usa', :primary => 'john', :secondary => 'steve'},
{:country => 'france', :primary => 'lira', :secondary => 'ben'},
{:country => 'germany', :primary => 'jeff', :secondary => ''}
]
我可以通过遍历数组并将值放入“primary”的哈希来实现。如何将“secondary”添加到可能已插入数组的现有哈希中?
答案 0 :(得分:11)
稍微高阶编程:
myarray.reduce({}) do |accu, (country, func, name)|
accu[country] ||= {}
accu[country][func.to_sym] = name
accu
end.map{|k, h| h[:country] = k; h}
Reduce将采用累加器,在这种情况下,我们从空哈希开始并遍历数组。我们将数组中的三元组与变量country, func, name
匹配。由于我们希望按国家/地区分组,因此我们将其创建为第一个Hash密钥。它应该包含一个哈希,所以我们确保它对应一个accu[country] ||= {}
的数组。
然后我们添加将func
转换为符号的键值对。最后,我们返回将被传递给下一次迭代的修改累加器。
这将返回如下数据结构:
{"usa"=>{:primary=>"john", :secondary=>"steve"},
"france"=>{:primary=>"lira", :secondary=>"ben"},
"germany"=>{:primary=>"jeff"}}
现在我们需要将它转换为散列数组而不是大散列。我们通过调用map
来执行此操作,并在此过程中添加country
作为哈希的键。
现在,上面的算法没有做的一件事是检查缺失值,resp。它并不保证:primary
和:secondary
都存在。你可以通过将map
修改为:
.map do |k, h|
h[:country] = k
h[:primary] ||= ""
h[:secondary] ||= ""
h
end
答案 1 :(得分:5)
这是一种有趣的,虽然令人困惑的方式。
format = Hash.new{ |h,k| h[k] = {:country => k, :primary => '', :secondary => ''} }
myarray.inject(format){ |result, (c,k,v)| result[c][k.to_sym] = v; result }.values
# => [
{:country=>"usa", :primary=>"john", :secondary=>"steve"},
{:country=>"france", :primary=>"lira", :secondary=>"ben"},
{:country=>"germany", :primary=>"jeff", :secondary=>""} ]
基本上format
哈希定义了您想要生成输出的方式。 inject
来电按国家/地区收集结果。 values
调用只是在没有国家/地区哈希键的情况下获取实际结果。