Я не могу заставить себя добавить метод merge_method
в класс Hash
, не только потому, что он загрязняет основной класс, но и потому, что он применим только к небольшому подмножеству хэшей, для которых все значенияявляются числовыми
Можно refine
Hash
, как это сделал @Amadan, но я думаю, что имеет больше смысла просто создать метод, похожий на методы модуля, которые ведут себя как функции (например, Math::sqrt
), чтопринимает все хэши в качестве аргументов.
def sum_values_by_key(*hashes)
hashes.each_with_object(Hash.new(0)) { |g,h| g.each { |k,v| h[k] += v } }
end
sum_values_by_key({ "a" => 200, "b" => 100 }, { "b" => 100, "c" => 300 })
#=> {"a"=>200, "b"=>200, "c"=>300}
sum_values_by_key({ "a" => 200, "b" => 100 }, { "b" => 100, "c" => 300 },
{ "a" => 150, "c" => 250 })
#=> {"a"=>350, "b"=>200, "c"=>550}
Используется форма Hash :: new , которая определяет значение по умолчанию, которое здесь равно нулю. Выражение:
h[k] += v
расширяется до:
h[k] = h[k] + v
Если этот хэш был определен h = Hash.new(0)
и h
имеет ключ k
, h[k]
справаравенства вычисляется для возврата значения k
. Однако, если h
не имеет ключа k
, h[k]
справа возвращает значение по умолчанию, ноль, чтобы стать:
h[k] = 0 + v
Я также изменил имя метода насделать его более значимым.