我有两个哈希数组,如下所示:
a = [ { car_id: 1, motor_id: 1, quantity: 5 },
{ car_id: 1, motor_id: 2, quantity: 6 },
{ car_id: 5, motor_id: 3, quantity: 3 } ]
b = [ { car_id: 1, motor_id: 1, quantity: 2 },
{ car_id: 1, motor_id: 2, quantity: 3 } ]
我希望将b
中每个哈希值的数量从a
中的哈希值中减去那些具有相同car_id
&的哈希值的哈希值。 motor_id
。所以,我的预期结果是:
c = [ {car_id: 1, motor_id: 1, quantity: 3},
{car_id: 1, motor_id: 2, quantity: 3},
{car_id: 5, motor_id: 3, quantity: 3 } ]
在Ruby中执行此操作的好方法是什么?我的想法是迭代a
,并且对于每个元素,查找b
中是否有car_id
和motor_id
相同,如果是,则减去并继续
答案 0 :(得分:2)
我建议您首先为bqty
创建哈希b
,对于g
的每个元素(哈希)b
,将[g[:car_id], g[:motor_id]]
映射到{{ 1}}:
g[:quantity]
接下来,将bqty = b.each_with_object({}) {|g,h| h[[g[:car_id], g[:motor_id]]] = g[:quantity]}
#=> {[1, 1]=>2, [1, 2]=>3}
的每个元素(哈希)g
映射到所需的哈希值。这是通过将a
合并到空哈希g
(或h
)来完成的,然后,如果有g.dup
的元素与密钥bqty
,从key = [h[:car_id], h[:motor_id]]
中减去bqty[key]
。请注意,这会使h[:quantity]
和a
保持不变。
b
antepenultimate 1 系列的替代品是:
a.map do |g|
{}.merge(g).tap do |h|
key = [h[:car_id], h[:motor_id]]
h[:quantity] -= bqty[key] if bqty.key?(key)
end
end
#=> [{:car_id=>1, :motor_id=>1, :quantity=>3},
# {:car_id=>1, :motor_id=>2, :quantity=>3},
# {:car_id=>5, :motor_id=>3, :quantity=>3}]
自 h[:quantity] -= bqty[key].to_i
。
1。如何放弃使用这样一个词的机会?
答案 1 :(得分:0)
这基本上就是您的建议,除了明确检查car_id
/ motor_id
之外,它使用的是哈希。
ids = ->(h){h.values_at(:car_id, :motor_id)} # A function for extracting the key values
lookup = Hash[*a.flat_map{|h| [ids[h], h]}] # A map from ids -> hash w/ quantity
b.each{|h| lookup[ids[h]][:quantity] -= h[:quantity]} # Subtract each b from an a (will error if the a doesn't exist)
a == c # == true
答案 2 :(得分:0)
也许,您会发现以下内容更直观:
matched_result = []
while current_a = a.shift
if current_b = b.shift
if current_a[:car_id] == current_b[:car_id] && current_a[:motor_id] == current_b[:motor_id]
matched_result << {car_id: current_a[:car_id], motor_id: current_a[:motor_id], quantity: current_a[:quantity] - current_b[:quantity]}
end
else
matched_result << current_a
end
end
p matched_result