我有两个哈希数组 - car_model
& car_cc
如下。对于car_model
中的每个哈希,我需要查找cc
密钥并将其添加到car_model
。
car_model = [
{state: "MH", regno: 5555, model: "alto"},
{state: "MH", regno: 5566, model: "alto"},
{state: "DL", regno: 5555, model: "prius"},
{state: "DL", regno: 5567, model: "nano"}
]
car_cc = [
{state: "MH", regno: 5555, cc: 999},
{state: "MH", regno: 5588, cc: 1800},
{state: "DL", regno: 5555, cc: 1119},
{state: "DL", regno: 5567, cc: nil}
]
现在我使用常规的.each
循环来查找cc
中的car_cc
密钥,并将其添加到car_model
中的每个项目。
car_model.each do |cm|
car_cc.each do |cc|
if(cm["state"]==cc["state"] && cm["regno"]==cc["regno"])
cm["cc"] = cc["cc"]
break
end
end
end
预期产出
puts car_model
{:state=>"MH", :regno=>5555, :model=>"alto", :cc=>999}
{:state=>"MH", :regno=>5566, :model=>"alto", :cc=>nil}
{:state=>"DL", :regno=>5555, :model=>"prius", :cc=>1119}
{:state=>"DL", :regno=>5567, :model=>"nano", :cc=>nil}
=> nil
irb(main):008:0>
有更有效的方法吗 - 更快,更红宝石的方式?
答案 0 :(得分:4)
一种方法是使用方便的键将car_cc
转换为哈希:
cc = car_cc.each_with_object({}) { |car, h| h[car.values_at(:state, :regno)] = car[:cc] }
这样您就可以更轻松地执行连接:
car_model.each { |h| h[:cc] = cc[h.values_at(:state, :regno)] }
这假设:state
/ :regno
对在car_cc
中是唯一的,并且您要修改car_model
。如果您不想修改car_model
,那么您可以说:
car_model_cc = car_model.map { |cm| cm.merge(cc: cc[cm.values_at(:state, :regno)]) }
在添加:cc
时复制所有内容。
当然,对于数据集这么小,任何性能差异都太小而不用担心,如果你的数据集要大得多,那么你可能想把它全部填入数据库中,让数据库完成繁重的任务。
答案 1 :(得分:2)
car_model.map do |cm|
cm.merge(car_cc.detect do |e|
e[:state] == cm[:state] && e[:regno] == cm[:regno]
end || {cc: nil})
end
或,DRY:
VALS = %i|state regno|
car_model.map do |cm|
cm.merge(car_cc.detect do |e|
[e, cm].map { |e| e.values_at(*VALS) }.reduce(:==)
end || {cc: nil})
end
如果要查找的项目数量足够大,我将从构建中间对象开始:
map = car_cc.group_by { |e| e.values_at(:state, :regno) }
.map { |k, v| [k, v.first[:cc]] }.to_h
#⇒ {
# [ "MH", 5555 ] => 999,
# [ "MH", 5588 ] => 1800,
# [ "DL", 5555 ] => 1119,
# [ "DL", 5567 ] => nil
# }
现在一切顺利:
car_model.each do |cm|
cm[:cc] = map[[cm[:state], cm[:regno]]]
end
答案 2 :(得分:1)
model = car_model.each_with_object({}) { |g,h|
h[g.values_at(:state, :regno)] = g.merge(:cc => nil) }
#=> {["MH", 5555]=>{:state=>"MH", :regno=>5555, :model=>"alto", :cc=>nil},
# ["MH", 5566]=>{:state=>"MH", :regno=>5566, :model=>"alto", :cc=>nil},
# ["DL", 5555]=>{:state=>"DL", :regno=>5555, :model=>"prius", :cc=>nil},
# ["DL", 5567]=>{:state=>"DL", :regno=>5567, :model=>"nano", :cc=>nil}}
cc = car_cc.each_with_object({}) { |g,h| h[g.values_at(:state, :regno)] = g }.
select { |k,_| model.key?(k) }
#=> {["MH", 5555]=>{:state=>"MH", :regno=>5555, :cc=>999},
# ["DL", 5555]=>{:state=>"DL", :regno=>5555, :cc=>1119},
# ["DL", 5567]=>{:state=>"DL", :regno=>5567, :cc=>nil}}
(model.merge(cc) { |_,o,n| o.merge(n) }).values
#=> [{:state=>"MH", :regno=>5555, :model=>"alto", :cc=>999},
# {:state=>"MH", :regno=>5566, :model=>"alto", :cc=>nil},
# {:state=>"DL", :regno=>5555, :model=>"prius", :cc=>1119},
# {:state=>"DL", :regno=>5567, :model=>"nano", :cc=>nil}]
备注强>
在计算cc
时,我们首先计算以下哈希值,然后删除k,v
不包含密钥model
的键值对k
。
car_cc.each_with_object({}) { |g,h| h[g.values_at(:state, :regno)] = g }
#=> {["MH", 5555]=>{:state=>"MH", :regno=>5555, :cc=>999},
# ["MH", 5588]=>{:state=>"MH", :regno=>5588, :cc=>1800},
# ["DL", 5555]=>{:state=>"DL", :regno=>5555, :cc=>1119},
# ["DL", 5567]=>{:state=>"DL", :regno=>5567, :cc=>nil}}
在最后一行代码中,我们在提取其值之前计算以下哈希值。
model.merge(cc) { |_,o,n| o.merge(n) }
#=> {["MH", 5555]=>{:state=>"MH", :regno=>5555, :model=>"alto", :cc=>999},
# ["MH", 5566]=>{:state=>"MH", :regno=>5566, :model=>"alto", :cc=>nil},
# ["DL", 5555]=>{:state=>"DL", :regno=>5555, :model=>"prius", :cc=>1119},
# ["DL", 5567]=>{:state=>"DL", :regno=>5567, :model=>"nano", :cc=>nil}}
最后一次计算使用Hash#merge的形式,它使用一个块来确定合并的两个哈希中存在的键的值。有关三个块变量的解释,请参阅doc(此处_
,o
和n
,第一个是下划线,仅表示该块变量未在块计算中使用)