如何使用从值创建并按其分组的键创建哈希对象?
cars = [{
id: 1,
properties: {
name: "audi",
type: "petrol"
},
},{
id: 1,
properties: {
name: "ford",
type: "petrol"
}
},{
id: 1,
properties: {
name: "tesla",
type: "electric"
}
}]
期望效果:
{
petrol: [{name: "audi"}, {name: "ford"}],
electric: [{name: "tesla"}]
}
我当前的功能会产生预期的效果,但它太长了,如何用更短的代码获得相同的效果?
cars.map { |c| Hash[c[:properties][:type], c[:properties][:name]] }.group_by{|h| h.keys.first}.each_value{|a| a.map!{|h| h.values.first}}
答案 0 :(得分:4)
grouped_cars
变量提取到单独的方法中。
grouped_cars = cars.inject({}) do |result, car|
result[car[:properties][:type]] ||= []
result[car[:properties][:type]] << { name: car[:properties][:name] }
result
end
{ cars: grouped_cars }
答案 1 :(得分:2)
我的变体:
{
cars: cars.inject({}) do |hash, data|
type, name = data[:properties].values_at(:type, :name)
hash[type] ||= []
hash[type] << {name: name}
hash
end
}
甚至更短:
{
cars: cars.inject(Hash.new([])) do |hash, car|
type, name = car[:properties].values_at(:type, :name);
hash[type] += [{ name: name }];
hash
end
}
答案 2 :(得分:2)
inject
方法每次都必须返回备忘录,我认为each_with_object更好。
cars.each_with_object({}) do |item, hash|
(hash[item[:properties][:type]] ||= []) << { name: item[:properties][:name] }
end
=> {"petrol"=>[{:name=>"audi"}, {:name=>"ford"}], "electric"=>[{:name=>"tesla"}]}
答案 3 :(得分:0)
我建议如下:
cars.map { |h| h[:properties] }.each_with_object({}) { |g,h|
h.update(g[:type]=>[{ name: g[:name] }]) { |_,o,n| {name: o+n } } }
#=> {"petrol"=>{:name=>[{:name=>"audi"}, {:name=>"ford"}]},
# "electric"=>[{:name=>"tesla"}]}
首先,我们获得:
cars.map { |h| h[:properties] }
#=> [{:name=>"audi", :type=>"petrol"},
# {:name=>"ford", :type=>"petrol"},
# {:name=>"tesla", :type=>"electric"}]
然后我们使用使用该块的Hash#update(aka merge!
)形式:
{ |_,o,n| { name: o+n } }
确定合并的两个哈希中存在的键的值。
最初,哈希:
{ "petrol"=>[{ :name=>"audi"] }] }
被合并到由块变量h
表示的空哈希中。此合并不会使用该块,因为h
为空,因此没有键"petrol"
。
接下来,哈希:
{ "petrol"=>[{ :name=>"ford" }] }
合并到h
。由于此哈希值和h
都有密钥"petrol"
,因此"petrol"
的值由块给出:
{ |_,o,n| { name: o+n } }
#=> {|_,[{ :name=>"audi" }] , [{ :name=>"ford" }]|
# [{ name: "audi" }] + [{ name: "ford" }] }
#=> [{ name: "audi" }, { name: "ford" }]
最后,哈希:
{ "electric"=>{ :name=>"tesla" } }
合并到h
。由于h
没有密钥"electric"
,因此不需要块来确定该密钥的值。