在另一个数组中查找哈希并在Ruby中减去

时间:2015-06-19 04:31:10

标签: ruby

我有两个哈希数组,如下所示:

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_idmotor_id相同,如果是,则减去并继续

3 个答案:

答案 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