2012-01-03 15 views
22

Ben böyle bir karma var. project başka karma nesne olduğu için Yakut dup yinelemeli

Ben denemek

, İşte

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} 

sen project['duration'] görebilirsiniz orijinal karma değiştirilir.

Karma'nın yinelemeli olarak duped veya cloned olmasını istiyorum. Bunu nasıl başarabilirim? İşte

cevap

39

Eğer bu makul eski soruya bir cevap

d = Marshal.load(Marshal.dump(h)) 
+2

Bu, "h" ile başvurulan tüm nesnelerin tam kopyalarını oluşturur. Bu, basit String karmaları için Sayuj'un ihtiyaç duyduğu şey olabilir. Daha karmaşık nesneler ile, bu artık istenmeyebilir. Bir kez "hash # dup" yöntemini geçersiz kılmak için "hash'leri" yinelemeli olarak tüm hashları kopyalayabilirsiniz. Fakat bu her nesne tipi için uzatılmalıdır. –

+2

@HolgerJust: Evet, bu yüzden "derin kopya" diye tabir ettim :-) –

+1

Elbette. Sadece OP'den daha fazlasını yapabileceğinden bahsetmek istedim (her ne kadar muhtemelen iyi olsa da) :) Bu yüzden, sadece gelecekteki referanslar için. –

1

Ruby derin kopyalarını yapmak, ama benzer bir şey uygularken, onun üzerine oldu ben daha verimli bir yöntem uymak düşündüm nasıl . Yukarıdaki gibi basit, iki seviyeli derin karma için

, ayrıca böyle bir şey yapabilirsiniz:

d = h.inject({}) {|copy, (key, value)| 
    copy[key] = value.dup rescue value; copy 
} 

ben 4k elemanları, yüz her birkaç bayt ve birlikte karma bir karma bir test koştum Bu, Marshal.dump/load

'dan yaklaşık% 50 daha hızlıydı Elbette, 'project_name' alanının değeri gibi bir hashınız varsa işe yaramayacağı için tam olarak değil Basit 2 seviye karma için, harika/hızlı çalışır.

2

Marchal#dump/load çifti işe verilmezse, için Hash 'ın metodu #deep_dup yoktur yapabilirsiniz böylece: Eğer Rails

h = {'name' => 'sayuj', 
'age' => 22, 
'project' => {'project_name' => 'abc', 
       'duration' => 'prq'}} 

h1 = h.deep_dup 
+1

olduğunda bu yöntemin çalışmayacağını unutmayın, yöntem h.deep yerine h.deep_dup olmalıdır. dup – yopefonic

+0

'deep_dup' yöntemi, Sınıfı anonim bir sınıfa dönüştürecektir, önerilmez. –

+0

@TianChen örneği? –

0

Başka bir alternatif Tam_dup gem (tam açıklama: Ben bu gemin yazarıyım) kullanmaktır diziler, karma, yapılar ve kullanıcı tanımlı sınıflar için genişletilebilir.

kullanmak için:

require 'full_dup' 
# Other code omitted ... 
d = h.full_dup 

Ayrıca bu full_dup döngüler ve yineleme ile olanlar da dahil, karmaşık veri ilişkilerini ele alır unutmayın.