2013-05-21 4 views
1

Из того, что я понимаю, когда вы устанавливаете объект = другому, он всегда будет ссылкой, поэтому у нас есть методы, такие как .dup и .clone, чтобы фактически создать копия объекта, а не ссылка.Ruby hash.delete (: key) Удаление копий и клонов также

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

Код:

or_data = {title: 'some title', tracks: [ { name: 'track one', position: 0, 
    artist: 'orignal artist', composer: 'original composer', duration: '1:30' }, 
    { name: 'track two', position: 1, artist: 'some other guy', 
    composer: 'beethoven', duration: '2:10' } ] } 

new_hash = or_data.dup 
# or new_hash = or_data.clone, either way produces the same result 

or_data[:tracks].each { |e| e.delete(:position) } 

:position ключ также будет удален из new_hash!

Это происходит независимо от того, использую ли я .dup или .clone.

Я только что прочитал пост, который говорит, что нужно использовать:

new_hash = Marshal.load(Marshal.dump(or_data)) 

Это делает работу. Но почему? Потому что .dup и .clone делают «мелкие копии», то есть они будут создавать ссылку на :tracks (в этом примере) вместо копии, потому что это массив хэшей, содержащийся внутри хэша?

ответ

1

Взгляните на приведенный ниже код:

or_data = {title: 'some title', tracks: [ { name: 'track one', position: 0, artist: 'orignal artist', composer: 'original composer', duration: '1:30' }, { name: 'track two', position: 1, artist: 'some other guy', composer: 'beethoven', duration: '2:10' } ] } 
new_hash = or_data.dup 

p "Using .dup" 
p "-----------" 
p "or_data : #{or_data.object_id}" 
p "new_hash : #{new_hash.object_id}" 

p "or_data[:tracks] :#{or_data[:tracks].object_id}" 
p "new_hash[:tracks] : #{new_hash[:tracks].object_id}" 


or_data[:tracks].each { |e| e.delete(:position) } 


new_hash = Marshal.load(Marshal.dump(or_data)) 

p "Marshalling" 
p "-----------" 
p "or_data : #{or_data.object_id}" 
p "new_hash : #{new_hash.object_id}" 

p "or_data[:tracks] :#{or_data[:tracks].object_id}" 
p "new_hash[:tracks] : #{new_hash[:tracks].object_id}" 

Выход:

"Using .dup" 
"-----------" 
"or_data : 5282580" 
"new_hash : 5282568" 
"or_data[:tracks] :5282592" 
"new_hash[:tracks] : 5282592" 

"Marshalling" 
"-----------" 
"or_data : 5282580" 
"new_hash : 5282172" 
"or_data[:tracks] :5282592" 
"new_hash[:tracks] : 5282112" 

Причина ключ position удаляется при использовании .dup или .clone, потому что tracks ключ по-прежнему относится к одному и тому же объекту массива. Где после маршаллинга ключ tracks ссылается на весь новый объект массива.

1

Вы клонируете Hash object не Hash values. Он не выполняет вложенное клонирование.

В вашем случае массив ([ { name: 'track one', position: 0, artist: 'orignal artist', composer: 'original composer', duration: '1:30' }, { name: 'track two', position: 1, artist: 'some other guy', composer: 'beethoven', duration: '2:10' } ]) ссылается на тот же объект на clone или dup

 Смежные вопросы

  • Нет связанных вопросов^_^