Я считаю, что ваша проблема updated_hsh = my_hsh
.
Это не дублирует хеш. Любые изменения в updated_hsh
изменят my_hsh
и наоборот.
Использование Object # clone или Object # dup - шаг в правильном направлении, но фактически он не будет дублировать внутренние объекты (массивы "numbers"):
h1 = [{numbers: [1,2,3], n_count: 3}]
h2 = h1.map(&:clone)
h2[0][:numbers] << 4
h2[0][:n_count] += 1
h1
# => [{numbers: [1,2,3,4], n_count: 3}]
Вы можете видеть, что n_count
не был изменен в оригинале, но numbers
был.
Чтобы обойти это, вы можете использовать Hash # deep_dup . Этот метод недоступен в ядре Ruby. Это часть Active Support, которая требуется Rails и может быть легко загружена в обычную Ruby-программу, если вам нужен гем.
require 'active_support/all'
h1 = [{numbers: [1,2,3], n_count: 3}]
h2 = h1.map(&:deep_dup)
h2[0][:numbers] << 4
h2[0][:n_count] += 1
h1
# => [{numbers: [1,2,3], n_count: 3}]
Вы также можете реализовать deep_dup
самостоятельно, если не хотите использовать активную поддержку. См. Как создать глубокую копию объекта в Ruby?
Другой альтернативой является ручное построение внутренних хэшей, например:
h1 = [{numbers: [1,2,3], n_count: 3}]
h2 = h1.map do |hsh|
{
numbers: hsh[:numbers].clone,
n_count: hsh[:n_count]
}
end
Хотя deep_dup
более лаконичен