我该怎么做:
first_array = [
{:count=>nil, :date=>"Jan 31"},
{:count=>nil, :date=>"Feb 01"},
{:count=>nil, :date=>"Feb 02"},
{:count=>nil, :date=>"Feb 03"},
{:count=>nil, :date=>"Feb 04"},
{:count=>nil, :date=>"Feb 05"}
]
second_array = [
{:count=>12, :date=>"Feb 01"},
{:count=>2, :date=>"Feb 02"},
{:count=>2, :date=>"Feb 05"}
]
进入这个:
result = [
{:count=>nil, :date=>"Jan 31"},
{:count=>12, :date=>"Feb 01"},
{:count=>2, :date=>"Feb 02"},
{:count=>nil, :date=>"Feb 03"},
{:count=>nil, :date=>"Feb 04"},
{:count=>2, :date=>"Feb 05"}
]
我在SO上发现了类似的问题,但没有一个像这个一样简单。我可能会使用我不知道的方法/块组合。
答案 0 :(得分:3)
result_array = first_array.map do |first_hash|
second_array.each do |second_hash|
if first_hash[:date] == second_hash[:date]
first_hash[:count] = second_hash[:count]
break
end
end
first_hash
end
答案 1 :(得分:2)
此解决方案将优先考虑非零值
def hash_merge(h1, h2) h3 = {} h1.each do |k,v| h3[k] = h1[k].eql?(h2[k]) ? v : (h1[k].nil? ? h2[k] : h1[k]) end return h3 end result = [] first_array.each do |h1| h2 = {} second_array.each do |h| if h1[:date].eql?(h[:date]) h2 = h break end end result.push hash_merge(h1, h2) end p result
答案 2 :(得分:2)
<强> TL; DR 强>
使用each_with_object枚举:
first_array.each_with_object(second_array){ |e,a| a << e if a.none?{ |i| i[:date] == e[:date] } }
Long answe:r
我觉得有用的一种方法是each_with_object可枚举。整个方法可以写成:
first_array.each_with_object(second_array){ |e,a| a << e if a.none?{ |i| i[:date] == e[:date] } }
irb(main):025:0> pp first_array.each_with_object(second_array){ |e,a| a << e if a.none?{ |i| i[:date] == e[:date] } }
[{:count=>12, :date=>"Feb 01"},
{:count=>2, :date=>"Feb 02"},
{:count=>2, :date=>"Feb 05"},
{:count=>nil, :date=>"Jan 31"},
{:count=>nil, :date=>"Feb 03"},
{:count=>nil, :date=>"Feb 04"}]
当我们需要沿多个值进行比较时,这种方法也会起作用,例如: a.none?{ |i| i[:date] == e[:date] and i[:location] == e[:location] }
当数组元素是仅具有两个键的哈希值并且其中一个键是唯一的时,将数组转换为哈希是另一种解决方案。我们首先将两个数组转换为哈希值,然后将第一个数组与第二个数组合并,然后将其转换回哈希数组。
def array_of_hashed_dates_to_hash(a_of_h); a_of_h.each_with_object({}){ |e,h| h[e[:date]] = e[:count] }; end
array_of_hashed_dates_to_hash(first_array).merge(array_of_hashed_dates_to_hash(second_array)).map{|e| {date: e.first, count: e.last}}
irb(main):039:0> pp array_of_hashed_dates_to_hash(first_array).merge(array_of_hashed_dates_to_hash(second_array)).map{|e| {date: e.first, count: e.last}}
[{:date=>"Jan 31", :count=>nil},
{:date=>"Feb 01", :count=>12},
{:date=>"Feb 02", :count=>2},
{:date=>"Feb 03", :count=>nil},
{:date=>"Feb 04", :count=>nil},
{:date=>"Feb 05", :count=>2}]
第一种方法似乎更有效:
#!/usr/bin/ruby -Ku
require 'benchmark'
first_array = [
{:count=>nil, :date=>"Jan 31"},
{:count=>nil, :date=>"Feb 01"},
{:count=>nil, :date=>"Feb 02"},
{:count=>nil, :date=>"Feb 03"},
{:count=>nil, :date=>"Feb 04"},
{:count=>nil, :date=>"Feb 05"}
]
second_array = [
{:count=>12, :date=>"Feb 01"},
{:count=>2, :date=>"Feb 02"},
{:count=>2, :date=>"Feb 05"}
]
n = 1000
def array_of_hashed_dates_to_hash(a_of_h)
a_of_h.each_with_object({}){ |e,h| h[e[:date]] = e[:count] }
end
Benchmark.bm(20) do |x|
x.report("Compare by Hash value (each_with_object)") do
n.times do
first_array.each_with_object(second_array){ |e,a| a << e if a.none?{ |i| i[:date] == e[:date] } }
end
end
x.report("Convert to Hashes and merge") do
n.times do
first_array_hash = array_of_hashed_dates_to_hash(first_array)
second_array_hash = array_of_hashed_dates_to_hash(second_array)
first_array_hash.merge(second_array_hash).map{|e| {date: e.first, count: e.last}}
end
end
end
user system total real
Compare by Hash value (each_with_object) 0.000000 0.000000 0.000000 ( 0.008223)
Convert to Hashes and merge 0.020000 0.000000 0.020000 ( 0.012077)
答案 3 :(得分:1)
这可以满足您的需求:
result = first_array.map do |first_hash|
c = second_array.select do |second_hash|
second_hash[:date] == first_hash[:date]
end
if c.empty?
first_hash
else
c.first
end
end
N.B。:我假设first_array
始终与nil
:count
进行哈希,而second_array
则没有,如您的示例所示。
答案 4 :(得分:1)
我的建议是使用:date作为哈希的键,并将:count作为其值。 如果所有你需要它依靠日期,最好有类似的东西:
result_hash = { "Jan 31" => nil, "Feb 01" => 12, ...}
顺便说一下,如果所需的输出是那个,我建议这个解决方案:
all = first_array + second_array
result_hash = {}
all.each do |x|
result_hash[x[:date]] = x[:count]
end
result = []
result_hash.each_pair do |x, y|
result << {:count => y, :date => x}
end