@ArupRakshit回答,稍有修改(为了在最终示例中更清晰地表达加入了该函数):
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)
group(sample, :size, :name)
请注意,虽然问题中没有提到,但您可能希望保留原始的
sample
。一些答案对此进行了保留,而其他答案则没有。
在分组 (list.group_by {...}
) 后,执行转换的部分(不修改原始样本的值)如下:
.map { |k,v| [ k , v.map {|h| h[at]} ] }.to_h
一些提示:
- 迭代组的哈希(第一个“map”)中的对(pairs),其中
- 对于每次迭代,我们接收
|group_key,array]
并返回 [group_key,new_array]
的 Array
(外部 block
),
- 最后,
to_h
将 Array of Array
转换为 Hash
(将此 [[gk1,arr1],[gk2,arr2] ...]
转换为此 {gk1 => arr1,gk2 => arr2,...}
)
步骤(2)中未解释的一个遗漏步骤。
new_array
是由
v.map {| h | h[at]}
制成的,它只是将原始
Hash
的每个元素
array
(因此我们从
Array of Hash
转移到元素的
Array
)。
希望这能帮助其他人理解这个例子。
option_groups_from_collection_for_select
助手。 - Stefan