Ruby数组的哈希。 group_by并在一行中修改
我有一系列哈希,类似于
[ {:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"} ]
我想把它转换成这个
{ "Meat" => ["one", "two"], "Fruit" => ["Four"]}
我试过group_by
然后我得到了这个
{ "Meat" => [{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}], "Fruit" => [{:type=>"Fruit", :name=>"four"}] }
然后我不能修改它只留下名称而不是完整的哈希。 我需要在一行中执行此操作,因为对于Rails表单上的grouped_options_for_select
。
array.group_by{|h| h[:type]}.each{|_, v| v.replace(v.map{|h| h[:name]})} # => {"Meat"=>["one", "two"], "Fruit"=>["four"]}
遵循steenslag的建议:
array.group_by{|h| h[:type]}.each{|_, v| v.map!{|h| h[:name]}} # => {"Meat"=>["one", "two"], "Fruit"=>["four"]}
在初始数组的单次迭代中:
arry.inject(Hash.new([])) { |h, a| h[a[:type]] += [a[:name]]; h }
array = [{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"}] array.inject({}) {|memo, value| (memo[value[:type]] ||= []) << value[:name]; memo}
我会这样做:
hsh =[{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"}] p Hash[hsh.group_by{|h| h[:type] }.map{|k,v| [k,v.map{|h|h[:name]}]}] # >> {"Meat"=>["one", "two"], "Fruit"=>["four"]}
使用ActiveSuport的Hash#transform_values
:
array.group_by{ |h| h[:type] }.transform_values{ |hs| hs.map{ |h| h[:name] } } #=> {"Meat"=>["one", "two"], "Fruit"=>["four"]}
@ArupRakshit回答 ,略有修改(为了清晰起见,在最后的例子中添加了该function):
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
of groups(第一张map
),在哪里 - 对于每次迭代,我们收到
|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]}
v.map {|h| h[at]}
,它只是对array
的每个原始Hash
( h
)元素的值at
转换(所以我们从Array of Hash
es移动到一个元素Array
)。
希望能帮助他人理解这个例子。