2014-10-06 3 views
0

У меня есть два хеша, содержащих несколько хешей (информация о продукте).Как сравнить два хэша, содержащие ~ 25000 хэшей?

Что я хочу сделать, это сравнить два хэша и посмотреть, какие продукты были добавлены, удалены, обновлены (например, цена, описание, изображение).

old_hash.size 
# => 24595 

new_hash.size 
# => 26153 

Вот что структура двух хэшей выглядеть следующим образом:

{"wi230075"=> 
    {"itemId"=>"wi230075", 
    "description"=>"AH Verse frietaardappelen", 
    "salesUnitSize"=>"2,5 kg", 
    "images"=>[...] 
    "fromPrice"=>2.19, 
    "basePrice"=>{"price"=>2.19, "unitPriceDescription"=>"0.96/KG"}, 
    "score"=>0, 
    "frozen"=>false, 
    "isPBO"=>false, 
    "outOfStock"=>false, 
    "quantity"=>0, 
    "extendedAttributes"=>[], 
    "sourceId"=>{"source"=>"wi", "id"=>230075, "asString"=>"wi230075"}, 
    "hqIdSource"=>"AH_HQ", 
    "hqId"=>822729, 
    "productId"=>230075, 
    "links"=>[], 
    "category"=>"/Aardappel, groente, fruit/Aardappelen/Hele aardappel/", 
    "brand"=>"AH"}, 
    {...} 
} 

Я попытался сравнение двух хэшей с помощью HashDiff gem. Вот что я получаю:

diff = HashDiff.diff(old_hash, new_hash) 
diff.size 
# => 64378 

Нечто похожее на ошибку, не может быть 64378 изменений.

Что такое лучший способ сравнить два хэша?

Edit:

Я просто хотел бы знать, если продукт был добавлен, удален или отредактирован. Если бы это было так, достаточно простого true.

+1

Этот драгоценный камень не будет знать, какие внутренние хэши следует сравнивать, поэтому все кажется отличным в выходе, который вы получаете. – squiguy

+1

Почему, по вашему мнению, не может быть «64378»? Один новый элемент верхнего уровня будет создавать патчи 'N', где' N' - количество подключей. Взгляните на документацию внимательно. – mudasobwa

+3

Это, вероятно, должно быть сделано с использованием базы данных. Они действительно хороши в этой проблеме. –

ответ

2

Это вернет все ключи, которые были изменены (т. созданы, удалены или обновлены):

(old_hash.keys | new_hash.keys).select { |k| old_hash[k] != new_hash[k] } 

Чтобы получить конкретные вы можете сделать что-то вроде:

keys = (old_hash.keys | new_hash.keys) 
new_keys = keys.select { |k| old_hash[k].nil? } 
deleted_keys = keys.select { |k| new_hash[k].nil? } 
modified_keys = keys.select { |k| old_hash[k] != new_hash[k] } 
unchanged_keys = keys - (new_keys | deleted_keys | modified_keys) 

Это предполагает, что вы не заинтересованы в ключах с нулевыми значениями. Если вы тогда, то вы, очевидно, должны заменить .nil? звоните с чем-то другим.

1

Я не проверить код, но я думаю, что это выглядит как этот

Чтобы получить дополнительную запись:

added_keys = new_hash.keys - old_hash.keys 
added_records = new_hash.select{|k,v| added_keys.include? k} 

Чтобы получить удаленную запись:

removed_keys = old_hash.keys - new_hash.keys 
removed_records = old_hash.select{|k,v| removed_keys.include? k} 

Для получить измененную запись:

changed_records = new_hash.select do |k,v| 
    old_hash.has_key?(k) && (old_hash[k]["description"] != new_hash[k]["description"] || old_hash[k]["images"] != new_hash[k]["images"] || old_hash[k]["basePrice"] != new_hash[k]["basePrice"]) 
end 
Смежные вопросы