@ArupRakshit answer,稍作修改(为了清楚起见,在最后一个示例中添加了该函数):
def group(list, by, at)
list.group_by { |h| h[by] }.map { |k,v| [ k , v.map {|h| h[at]} ] }.to_h
end
sample =[
{:type=>"Meat", :name=>"one", :size=>"big" },
{:type=>"Meat", :name=>"two", :size=>"small" },
{:type=>"Fruit", :name=>"four", :size=>"small" }
]
group(sample, :type, :name) # => {"Meat"=>["one", "two"], "Fruit"=>["four"]}
group(sample, :size, :name) # => {"big"=>["one"], "small"=>["two", "four"]}
请注意,尽管问题中未提及,但您可能希望按原样保留原件sample
。一些答案保留了这一点,而另一些则没有。
在分组 ( list.group_by {...}
) 之后,进行转换的部分(不修改原始样本的值)是:
.map { |k,v| [ k , v.map {|h| h[at]} ] }.to_h
一些提示:
- 迭代成对的
Hash
组(第一个map
),其中
- 对于每次迭代,我们接收
|group_key, array]
并返回一个Array
of [group_key, new_array]
(outer block
),
- 最后
to_h
将Array of Array
s 转换为Hash
(this[[gk1,arr1],[gk2,arr2]...]
转换为 this { gk1 => arr1, gk2 => arr2, ...}
)
上面的步骤(2)中没有说明一个缺失的步骤。new_array
is made by v.map {|h| h[at]}
,它只是转换at
每个原始Hash
( h
) 元素的值array
(所以我们从Array of Hash
es 移动到 an Array
of 元素)。
希望能帮助其他人理解这个例子。