Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 从多个哈希数组构建一个新的哈希数组_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails 从多个哈希数组构建一个新的哈希数组

Ruby on rails 从多个哈希数组构建一个新的哈希数组,ruby-on-rails,ruby,Ruby On Rails,Ruby,我有以下三个哈希数组 customer_mapping = [ {:customer_id=>"a", :customer_order_id=>"g1"}, {:customer_id=>"b", :customer_order_id=>"g2"}, {:customer_id=>"c", :customer_order_id=>"g3"}, {:customer_id=>"d", :customer_or

我有以下三个哈希数组

customer_mapping = [
      {:customer_id=>"a", :customer_order_id=>"g1"},
      {:customer_id=>"b", :customer_order_id=>"g2"},
      {:customer_id=>"c", :customer_order_id=>"g3"},
      {:customer_id=>"d", :customer_order_id=>"g4"},
      {:customer_id=>"e", :customer_order_id=>"g5"}
    ]

customer_with_products = [
      {:customer_order_id=>"g1", :product_order_id=>"a1"},
      {:customer_order_id=>"g2", :product_order_id=>"a2"},
      {:customer_order_id=>"g3", :product_order_id=>"a3"},
      {:customer_order_id=>"g4", :product_order_id=>"a4"},
      {:customer_order_id=>"g5", :product_order_id=>"a5"}
    ]

product_mapping = [
    {:product_id=>"j", :product_order_id=>"a1"},
    {:product_id=>"k", :product_order_id=>"a2"},
    {:product_id=>"l", :product_order_id=>"a3"}
  ]
我想要的是一个只有客户id和产品id的新哈希

{:product_id=>"j", :customer_id=>"a"},
{:product_id=>"k", :customer_id=>"b"},
{:product_id=>"l", :customer_id=>"c"}
我尝试在产品映射上循环,并选择客户中与产品匹配的客户订单id,然后考虑在客户映射上循环,但无法从第一步获得所需的输出

如何实现这一点?

使用

def merge_by(a,b, key)
  (a+b).group_by { |h| h[key] }
       .each_value.map { |arr| arr.inject(:merge) }
end

merge_by(
  merge_by(customer_mapping, customer_with_products, :customer_order_id),
  product_mapping,
  :product_order_id
).select { |h| h[:product_id] }.map { |h| h.slice(:product_id, :customer_id) }

#=>[{:product_id=>"j", :customer_id=>"a"},
#   {:product_id=>"k", :customer_id=>"b"},
#   {:product_id=>"l", :customer_id=>"c"}]
绝对不是最干净的解决方案,如果您的初始数组来自SQL查询,我认为可以修改这些查询以正确聚合数据

merge_by(customer_mapping, customer_with_products, :customer_order_id)
# => [{:customer_id=>"a", :customer_order_id=>"g1", :product_order_id=>"a1"},
#     {:customer_id=>"b", :customer_order_id=>"g2", :product_order_id=>"a2"},
#     {:customer_id=>"c", :customer_order_id=>"g3", :product_order_id=>"a3"},
#     {:customer_id=>"d", :customer_order_id=>"g4", :product_order_id=>"a4"},
#     {:customer_id=>"e", :customer_order_id=>"g5", :product_order_id=>"a5"}]
然后以类似方式将其与上一个数组合并,并清理结果,只选择找到其
:product_id
的元素,切片想要的键

或者,更具可读性的解决方案(取决于数组大小)可能会更慢,因为它会不断迭代散列:

product_mapping.map do |hc| 
  b_match = customer_with_products.detect { |hb| hb[:product_order_id] == hc[:product_order_id] }
  a_match = customer_mapping.detect { |ha| ha[:customer_order_id] == b_match[:customer_order_id] }
  [hc, a_match, b_match].inject(:merge)
end.map { |h| h.slice(:product_id, :customer_id) }
使用

绝对不是最干净的解决方案,如果您的初始数组来自SQL查询,我认为可以修改这些查询以正确聚合数据

merge_by(customer_mapping, customer_with_products, :customer_order_id)
# => [{:customer_id=>"a", :customer_order_id=>"g1", :product_order_id=>"a1"},
#     {:customer_id=>"b", :customer_order_id=>"g2", :product_order_id=>"a2"},
#     {:customer_id=>"c", :customer_order_id=>"g3", :product_order_id=>"a3"},
#     {:customer_id=>"d", :customer_order_id=>"g4", :product_order_id=>"a4"},
#     {:customer_id=>"e", :customer_order_id=>"g5", :product_order_id=>"a5"}]
然后以类似方式将其与上一个数组合并,并清理结果,只选择找到其
:product_id
的元素,切片想要的键

或者,更具可读性的解决方案(取决于数组大小)可能会更慢,因为它会不断迭代散列:

product_mapping.map do |hc| 
  b_match = customer_with_products.detect { |hb| hb[:product_order_id] == hc[:product_order_id] }
  a_match = customer_mapping.detect { |ha| ha[:customer_order_id] == b_match[:customer_order_id] }
  [hc, a_match, b_match].inject(:merge)
end.map { |h| h.slice(:product_id, :customer_id) }

在处理问题后,解决方案如下:

result_hash_array = product_mapping.map do |product_mapping_entry|
        customer_receipt = customer_with_products.find do |customer_with_products_entry|
            product_mapping_entry[:product_order_id] == customer_with_products_entry[:product_order_id]
        end
        customer_id = customer_mapping.find do |customer_mapping_entry|
            customer_receipt[:customer_order_id] == customer_mapping_entry[:customer_order_id]
        end[:customer_id]
        {product_id: product_mapping_entry[:product_id], customer_id: customer_id}
end
输出

results_hash_array => [{:product_id=>"j", :customer_id=>"a"},
                       {:product_id=>"k", :customer_id=>"b"},
                       {:product_id=>"l", :customer_id=>"c"}]

在处理问题后,解决方案如下:

result_hash_array = product_mapping.map do |product_mapping_entry|
        customer_receipt = customer_with_products.find do |customer_with_products_entry|
            product_mapping_entry[:product_order_id] == customer_with_products_entry[:product_order_id]
        end
        customer_id = customer_mapping.find do |customer_mapping_entry|
            customer_receipt[:customer_order_id] == customer_mapping_entry[:customer_order_id]
        end[:customer_id]
        {product_id: product_mapping_entry[:product_id], customer_id: customer_id}
end
输出

results_hash_array => [{:product_id=>"j", :customer_id=>"a"},
                       {:product_id=>"k", :customer_id=>"b"},
                       {:product_id=>"l", :customer_id=>"c"}]

其他选项,从客户映射开始,一行(但相当宽):


其他选项,从客户映射开始,一行(但相当宽):

这种配方特别容易测试。(非常简单,不需要调试)


这种配方特别容易测试。(非常简单,不需要调试)。

我建议您选择一个更长但更具可读性的解决方案,您也可以在几个月后通过查看了解它。使用散列键的全名,而不是将它们隐藏在
k,v
后面,以获得更复杂的查找(可能这只是我个人的偏好)

我建议你这样想:

result = product_mapping.map do |mapping|
  customer_id = customer_mapping.find do |hash|
    hash[:customer_order_id] == customer_with_products.find do |hash|
      hash[:product_order_id] == mapping[:product_order_id]
    end[:customer_order_id]
  end[:customer_id]

  { product_id: mapping[:product_id], customer_id: customer_id }
end

我建议您选择一个更长但更具可读性的解决方案,您也可以在几个月后通过查看了解它。使用散列键的全名,而不是将它们隐藏在
k,v
后面,以获得更复杂的查找(可能这只是我个人的偏好)

我建议你这样想:

result = product_mapping.map do |mapping|
  customer_id = customer_mapping.find do |hash|
    hash[:customer_order_id] == customer_with_products.find do |hash|
      hash[:product_order_id] == mapping[:product_order_id]
    end[:customer_order_id]
  end[:customer_id]

  { product_id: mapping[:product_id], customer_id: customer_id }
end