Ответ 1
Вот как вы делаете глубокие копии в Ruby
d = Marshal.load( Marshal.dump(h) )
У меня есть хэш вроде:
h = {'name' => 'sayuj',
'age' => 22,
'project' => {'project_name' => 'abc',
'duration' => 'prq'}}
Мне нужен дубликат этого хэша, это изменение не должно влиять на исходный хэш.
Когда я пытаюсь,
d = h.dup # or d = h.clone
d['name'] = 'sayuj1'
d['project']['duration'] = 'xyz'
p d #=> {"name"=>"sayuj1", "project"=>{"duration"=>"xyz", "project_name"=>"abc"}, "age"=>22}
p h #=> {"name"=>"sayuj", "project"=>{"duration"=>"xyz", "project_name"=>"abc"}, "age"=>22}
Здесь вы можете увидеть, что project['duration']
изменен в исходном хэше, потому что project
- еще один хеш-объект.
Я хочу, чтобы хэш был duped
или cloned
рекурсивно. Как я могу достичь этого?
Вот как вы делаете глубокие копии в Ruby
d = Marshal.load( Marshal.dump(h) )
Если пара Marchal
#dump/load
не работает, для rails существует метод Hash
#deep_dup
, поэтому вы можете:
h = {'name' => 'sayuj',
'age' => 22,
'project' => {'project_name' => 'abc',
'duration' => 'prq'}}
h1 = h.deep_dup
Если вы находитесь в Rails: Hash.deep_dup
Это ответ на достаточно старый вопрос, но я столкнулся с этим, когда я реализовал что-то похожее, подумал, что я буду использовать более эффективный метод.
Для простого, двухуровневого глубокого хаша, как и выше, вы также можете сделать что-то вроде этого:
d = h.inject({}) {|copy, (key, value)|
copy[key] = value.dup rescue value; copy
}
Я проверил тест на хэш хэшей с 4k элементами, каждый из нескольких сотен байт, и он был примерно на 50% быстрее, чем Marshal.dump/load
Конечно, это не так полно, поскольку это не сработает, если у вас есть хеш, например, значение поля project_name, но для простого хэша уровня 2 он работает отлично/быстрее.