2012-01-03 24 views
22

मैं एक हैश की तरह है।रूबी dup/क्लोन रिकर्सिवली

जब मैं कोशिश,

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 रिकर्सिव हो। इसे कैसे प्राप्त किया जा सकता है?

उत्तर

39

यहाँ कैसे आप रूबी में गहरी प्रतियां बनाने

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

यह 'h' द्वारा संदर्भित सभी वस्तुओं की पूर्ण प्रतियां बनाता है। सरल स्ट्रिंग हैंश के लिए सियुज द्वारा यह आवश्यक हो सकता है। अधिक जटिल वस्तुओं के साथ, यह अब और वांछित नहीं हो सकता है। एक बार 'हैश # डुप्ली' विधि को सभी मानों को दोहराने के लिए 'मानों' में दोबारा डुप्लिकेट कर सकता है। लेकिन उसे हर ऑब्जेक्ट प्रकार के लिए विस्तारित करने की आवश्यकता होगी। –

+2

@ होल्डर जस्ट: हां, यही कारण है कि इसे "गहरी प्रति" कहा जाता है :-) –

+1

बेशक। मैं सिर्फ यह उल्लेख करना चाहता था कि यह ओपी से अधिक कर सकता है (हालांकि यह शायद ठीक है) :) तो यह सिर्फ भविष्य के संदर्भ के लिए है। –

1

यह एक यथोचित वर्ष प्रश्न का उत्तर है, लेकिन मैं कुछ इसी तरह लागू करने, जबकि इस पर हुआ, सोचा था कि मैं एक अधिक कुशल विधि के लिए झंकार करेंगे ।

ऊपर की तरह सरल, दो स्तर गहरी हैश के लिए, आप भी कुछ इस तरह कर सकते हैं:

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

मैं 4k तत्वों, प्रत्येक कुछ सौ बाइट्स, और साथ हैश के हैश पर एक परीक्षण भाग गया यह मार्शल डंप/लोड

बेशक यह पूर्ण नहीं है, क्योंकि यदि आपके पास हैश है, उदाहरण के लिए, 'project_name' फ़ील्ड का मान, लेकिन यह काम नहीं करेगा, लेकिन यह काम नहीं करेगा, लेकिन एक साधारण 2 स्तर हैश के लिए, यह महान/तेज काम करता है।

2

मामले में Marchal#dump/load जोड़ी काम नहीं कर रहा है, के लिए वहाँ विधि #deep_dup है एक Hash की है, तो आप कर सकते हैं:

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

h1 = h.deep_dup 
+1

विधि h.deep के बजाय h.deep_dup होना चाहिए। डुप्ली – yopefonic

+0

'deep_dup' विधि क्लास को अज्ञात कक्षा में बदल देगी, अनुशंसित नहीं है। –

+0

@TianChen उदाहरण? –

0

एक अन्य विकल्प full_dup मणि का उपयोग करना है (पूर्ण प्रकटीकरण: मैं उस मणि का लेखक हूं) जो सरणी, हैंश, structs को संभालता है, और उपयोगकर्ता परिभाषित वर्गों के लिए विस्तार योग्य है।

का उपयोग करें:

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

भी ध्यान रखें कि full_dup छोरों या प्रत्यावर्तन के साथ उन सहित जटिल डेटा रिश्तों को संभालती है।