TL; DR
使用each_with_object枚舉:
first_array.each_with_object(second_array){ |e,a| a << e if a.none?{ |i| i[:date] == e[:date] } }
龍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)