arrays - 如何将哈希数组与匹配的列值合并
问题描述
我想合并两个数组array1
并array2
匹配一个列值。两个数组之间的绘图 ID 可能匹配也可能不匹配。匹配列是 array1 中的绘图 ID 和 array2 中的绘图 ID。
主要是array1。array1 中的列值应首先出现在预期输出中。
如果 array2 与 array1 不匹配,则使用零值合并 array2 列名
array1 = [
{"Date" => "2019-01-01", "Plot ID" => 234},
{"Date" => "2019-01-01", "Plot ID" => 235},
{"Date" => "2019-01-01", "Plot ID" => 236},
{"Date" => "2019-01-01", "Plot ID" => 237},
{"Date" => "2019-01-01", "Plot ID" => 238},
{"Date" => "2019-01-01", "Plot ID" => 239},
{"Date" => "2019-01-01", "Plot ID" => 240},
{"Date" => "2019-01-01", "Plot ID" => 241}
]
array2 = [
{"Date" => "2019-01-01", "Plotting ID" => 234, "size"=> 20, "visit" => 10, "price" => 103},
{"Date" => "2019-01-01", "Plotting ID" => 500, "size"=> 40, "visit" => 22, "price" => 233},
{"Date" => "2019-01-01", "Plotting ID" => 236, "size"=> 25, "visit" => 34, "price" => 423},
{"Date" => "2019-01-01", "Plotting ID" => 600, "size"=> 79, "visit" => 55, "price" => 234}
]
预期输出:
[
{"Date" => "2019-01-01", "Plot ID" => 234, "size"=> 20, "visit" => 10, "price" => 103},
{"Date" => "2019-01-01", "Plot ID" => 235, "size"=> 0, "visit" => 0, "price" => 0},
{"Date" => "2019-01-01", "Plot ID" => 236, "size"=> 25, "visit" => 34, "price" => 423},
{"Date" => "2019-01-01", "Plot ID" => 237, "size"=> 0, "visit" => 0, "price" => 0},
{"Date" => "2019-01-01", "Plot ID" => 238, "size"=> 0, "visit" => 0, "price" => 0},
{"Date" => "2019-01-01", "Plot ID" => 239, "size"=> 0, "visit" => 0, "price" => 0},
{"Date" => "2019-01-01", "Plot ID" => 240, "size"=> 0, "visit" => 0, "price" => 0},
{"Date" => "2019-01-01", "Plot ID" => 241, "size"=> 0, "visit" => 0, "price" => 0}
]
解决方案
此答案仅在array2
不包含任何重复Plotting ID
值的情况下才有效。(如果有重复Plotting ID
,它仍然有效,但它使用数组中曾经存在的最后一条记录。)
array1 = [{"Date" => "2019-01-01", "Plot ID" => 234}, {"Date" => "2019-01-01", "Plot ID" => 235}, {"Date" => "2019-01-01", "Plot ID" => 236}, {"Date" => "2019-01-01", "Plot ID" => 237}, {"Date" => "2019-01-01", "Plot ID" => 238}, {"Date" => "2019-01-01", "Plot ID" => 239}, {"Date" => "2019-01-01", "Plot ID" => 240}, {"Date" => "2019-01-01", "Plot ID" => 241}]
array2 = [{"Date" => "2019-01-01", "Plotting ID" => 234, "size"=> 20, "visit" => 10, "price" => 103}, {"Date" => "2019-01-01", "Plotting ID" => 500, "size"=> 40, "visit" => 22, "price" => 233}, {"Date" => "2019-01-01", "Plotting ID" => 236, "size"=> 25, "visit" => 34, "price" => 423}, {"Date" => "2019-01-01", "Plotting ID" => 600, "size"=> 79, "visit" => 55, "price" => 234}]
array2_lookup = array2.map(&:dup).map { |record| [record.delete('Plotting ID'), record] }.to_h
array2_lookup.default = { 'size' => 0, 'visit' => 0, 'price' => 0 }
pp array1.map { |record| array2_lookup[record['Plot ID']].merge(record) }
# [{"Date"=>"2019-01-01", "size"=>20, "visit"=>10, "price"=>103, "Plot ID"=>234},
# {"size"=>0, "visit"=>0, "price"=>0, "Date"=>"2019-01-01", "Plot ID"=>235},
# {"Date"=>"2019-01-01", "size"=>25, "visit"=>34, "price"=>423, "Plot ID"=>236},
# {"size"=>0, "visit"=>0, "price"=>0, "Date"=>"2019-01-01", "Plot ID"=>237},
# {"size"=>0, "visit"=>0, "price"=>0, "Date"=>"2019-01-01", "Plot ID"=>238},
# {"size"=>0, "visit"=>0, "price"=>0, "Date"=>"2019-01-01", "Plot ID"=>239},
# {"size"=>0, "visit"=>0, "price"=>0, "Date"=>"2019-01-01", "Plot ID"=>240},
# {"size"=>0, "visit"=>0, "price"=>0, "Date"=>"2019-01-01", "Plot ID"=>241}]
上述解决方案首先循环array2
并将其转换为散列,方法是'Plotting ID'
从散列中删除键/值对并将值用作键。出于这个原因,我添加了.map(&:dup)
调用,以防止原始哈希值发生array2
变异。如果散列突变对您来说不是问题,您可以简单地删除它。
创建查找哈希后,我添加了一个在合并哈希时使用的默认值。现在剩下要做的就是循环array1
,查找记录(如果有的话)或使用默认值并将其与当前元素合并。
这个答案使键有些混乱,但是由于哈希无论如何都是基于键查找(不是键/值顺序),所以这应该不是一个大问题。如果您希望所有键的顺序相同,您可以通过将所有键提供为默认值,将它们的值设置为nil
(或任何其他值,因为它们被覆盖):
array2_lookup.default = { 'Date' => nil, 'size' => 0, 'visit' => 0, 'price' => 0 }
# ... ^ added placeholder for ordering purposes
# [{"Date"=>"2019-01-01", "size"=>20, "visit"=>10, "price"=>103, "Plot ID"=>234},
# {"Date"=>"2019-01-01", "size"=>0, "visit"=>0, "price"=>0, "Plot ID"=>235},
# {"Date"=>"2019-01-01", "size"=>25, "visit"=>34, "price"=>423, "Plot ID"=>236},
# {"Date"=>"2019-01-01", "size"=>0, "visit"=>0, "price"=>0, "Plot ID"=>237},
# {"Date"=>"2019-01-01", "size"=>0, "visit"=>0, "price"=>0, "Plot ID"=>238},
# {"Date"=>"2019-01-01", "size"=>0, "visit"=>0, "price"=>0, "Plot ID"=>239},
# {"Date"=>"2019-01-01", "size"=>0, "visit"=>0, "price"=>0, "Plot ID"=>240},
# {"Date"=>"2019-01-01", "size"=>0, "visit"=>0, "price"=>0, "Plot ID"=>241}]