আমি কিভাবে রুবিতে একটি হ্যাশ কপি করব?


197

আমি স্বীকার করব যে আমি কিছুটা রুবি নবাগত (এখন রেক স্ক্রিপ্ট লিখছি)। বেশিরভাগ ভাষায়, অনুলিপি নির্মাতাদের সন্ধান করা সহজ। আধ ঘণ্টা অনুসন্ধানে এটি রুবিতে পাওয়া যায় নি। আমি হ্যাশটির একটি অনুলিপি তৈরি করতে চাই যাতে আমি এটির আসল উদাহরণটিকে প্রভাবিত না করে পরিবর্তন করতে পারি।

কিছু প্রত্যাশিত পদ্ধতি যা উদ্দেশ্য হিসাবে কাজ করে না:

h0 = {  "John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
h1=Hash.new(h0)
h2=h1.to_hash

ইতিমধ্যে, আমি এই অদম্য কর্মসংস্থান অবলম্বন করেছি

def copyhash(inputhash)
  h = Hash.new
  inputhash.each do |pair|
    h.store(pair[0], pair[1])
  end
  return h
end

আপনি যদি সরল Hashবস্তুগুলির সাথে কাজ করে থাকেন তবে প্রদত্ত উত্তরটি ভাল। আপনি যদি নিয়ন্ত্রণ করেন না এমন জায়গাগুলি থেকে আসা হ্যাশ-জাতীয় বস্তুগুলির সাথে আপনি যদি ডিল করছেন তবে আপনারা হ্যাশের সাথে সদৃশ যুক্ত সিঙ্গলটন শ্রেণি চান কিনা তা বিবেচনা করা উচিত। দেখুন stackoverflow.com/questions/10183370/...
সিম

উত্তর:


223

cloneপদ্ধতি রুবি এর স্ট্যান্ডার্ড, বিল্ট-ইন ভাবে করতে হয় অগভীর-অনুলিপি :

irb(main):003:0> h0 = {"John" => "Adams", "Thomas" => "Jefferson"}
=> {"John"=>"Adams", "Thomas"=>"Jefferson"}
irb(main):004:0> h1 = h0.clone
=> {"John"=>"Adams", "Thomas"=>"Jefferson"}
irb(main):005:0> h1["John"] = "Smith"
=> "Smith"
irb(main):006:0> h1
=> {"John"=>"Smith", "Thomas"=>"Jefferson"}
irb(main):007:0> h0
=> {"John"=>"Adams", "Thomas"=>"Jefferson"}

নোট করুন যে আচরণটি ওভাররাইড করা হতে পারে:

এই পদ্ধতির শ্রেণিবদ্ধ আচরণ থাকতে পারে। যদি তা হয় তবে সেই আচরণটি #initialize_copyক্লাসের পদ্ধতির অধীনে নথিভুক্ত করা হবে ।


ক্লোনটি অবজেক্ট, বিটিডাব্লু তে একটি পদ্ধতি, তাই এতে সমস্ত কিছুতে অ্যাক্সেস থাকে। এখানে
ডিলান লেস

29
যারা অন্যান্য উত্তর পড়ছেন না তাদের জন্য এখানে আরও স্পষ্ট মন্তব্য যুক্ত করা যা এটি একটি অগভীর অনুলিপি করে।
গ্রাম্পাসৌরাস

#initialize_copy ডকুমেন্টেশন হ্যাশের জন্য উপস্থিত বলে মনে হচ্ছে না, যদিও এটির সাথে হ্যাশ ডক পৃষ্ঠায় লিঙ্ক রয়েছে রুবি -ডোক.আর.কম
কোরআর

14
এবং অন্যান্য রুবি শুরুর জন্য, "অগভীর অনুলিপি" এর অর্থ হ'ল প্রথম স্তরের নীচের প্রতিটি বস্তু এখনও একটি রেফারেন্স।
রবডাব্লু

9
নোট করুন এটি আমার জন্য নেস্টেড হ্যাশগুলির জন্য কার্যকর হয়নি (যেমন অন্যান্য উত্তরে উল্লিখিত হয়েছে)। আমি ব্যবহৃত Marshal.load(Marshal.dump(h))
bheeshmar

178

অন্যরা যেমন উল্লেখ করেছে, cloneএটি করবে। cloneহ্যাশ একটি অগভীর অনুলিপি তৈরি করুন যে সচেতন হন। ঐটাই বলতে হবে:

h1 = {:a => 'foo'} 
h2 = h1.clone
h1[:a] << 'bar'
p h2                # => {:a=>"foobar"}

যা ঘটছে তা হ্যাশের রেফারেন্সগুলি অনুলিপি করা হচ্ছে তবে রেফারেন্সগুলি উল্লেখ করে এমন বস্তু নয়।

আপনি যদি একটি গভীর অনুলিপি চান তবে:

def deep_copy(o)
  Marshal.load(Marshal.dump(o))
end

h1 = {:a => 'foo'}
h2 = deep_copy(h1)
h1[:a] << 'bar'
p h2                # => {:a=>"foo"}

deep_copyমার্শাল করা যায় এমন যে কোনও অবজেক্টের জন্য কাজ করে। সর্বাধিক অন্তর্নির্মিত ডেটা ধরণের (অ্যারে, হ্যাশ, স্ট্রিং এবং সি।) মার্শাল করা যেতে পারে।

মার্শালিং সিরিয়ালের জন্য রুবির নাম । মার্শেলিংয়ের মাধ্যমে, অবজেক্টটি - বস্তুগুলির সাথে এটি নির্দেশ করে - এটি বাইটের একটি সিরিজে রূপান্তরিত হয়; সেই বাইটগুলি তারপরে মূলটির মতো অন্য কোনও বস্তু তৈরি করতে ব্যবহৃত হয়।


এটি দুর্দান্ত যে আপনি গভীর অনুলিপি সম্পর্কে তথ্য সরবরাহ করেছেন, তবে এটি একটি সতর্কতা নিয়ে আসা উচিত যা এটি অনিচ্ছাকৃত পার্শ্ব প্রতিক্রিয়া সৃষ্টি করতে পারে (উদাহরণস্বরূপ, হ্যাশ উভয়কে সংশোধন করে)। একটি হ্যাশকে ক্লোন করার মূল উদ্দেশ্য হ'ল আসল (অপরিবর্তনযোগ্যতা ইত্যাদির জন্য) পরিবর্তন রোধ করা।
কে। কার্পেন্টার

6
@ কে। কার্পেন্টার এটি কোনও অগভীর অনুলিপি নয় যা মূল অংশগুলি ভাগ করে দেয়? ডিপ অনুলিপি, যেমনটি আমি এটি বুঝতে পারি, এমন একটি অনুলিপি যা মূলটির কোনও অংশ ভাগ করে না, সুতরাং কোনওটি পরিবর্তন করে অপরটিকে সংশোধন করে না।
ওয়েন কনরাড

1
Marshal.load(Marshal.dump(o))গভীর কপিটি ঠিক কীভাবে হয় ? পর্দার আড়ালে কী ঘটে তা আমি সত্যিই বুঝতে পারি না
মুনতাসির আলম

এই হাইলাইট পাশাপাশি যে যদি আপনি না হয় h1[:a] << 'bar'আপনি আসল বস্তু সংশোধন করুন (স্ট্রিং H1 দ্বারা প্রতি ইঙ্গিত [: একটি]) কিন্তু যদি আপনি না ছিল h1[:a] = "#{h1[:a]}bar"পরিবর্তে, আপনি বিন্দু একটি নতুন স্ট্রিং অবজেক্ট তৈরি করবে, এবং h1[:a]যে, যখন h2[:a]হয় এখনও পুরানো (মোডবিহীন) স্ট্রিংয়ের দিকে ইশারা করছে।
ম্যাক্স উইলিয়ামস

@ মুনতাসিরআলাম আমি মার্শালিং কী করে তা সম্পর্কে কয়েকটি শব্দ যুক্ত করেছি। আমি আশা করি এটি সাহায্য করবে.
ওয়েইন কনরাড

73

আপনি যদি রেলগুলি ব্যবহার করেন তবে আপনি এটি করতে পারেন:

h1 = h0.deep_dup

http://apidock.com/rails/Hash/deep_dup


2
3 টি রেয়েলগুলিতে হ্যাশগুলির মধ্যে ডিপ_ডুপিং অ্যারেগুলির সাথে একটি সমস্যা রয়েছে। রেল 4 এটি স্থির করে।
পিডবব


13

বিদ্যমান হ্যাশ থেকে হ্যাশ একটি নতুন হ্যাশ তৈরি করতে পারে:

irb(main):009:0> h1 = {1 => 2}
=> {1=>2}
irb(main):010:0> h2 = Hash[h1]
=> {1=>2}
irb(main):011:0> h1.object_id
=> 2150233660
irb(main):012:0> h2.object_id
=> 2150205060

24
মনে রাখবেন যে এটিতে # ক্লোন এবং # ডুপের মতো একই গভীর অনুলিপি সমস্যা রয়েছে।
forforf

3
@ ফোরফ সঠিক আপনি গভীর বনাম অগভীর অনুলিপি বুঝতে না পারলে ডেটা স্ট্রাকচার অনুলিপি করার চেষ্টা করবেন না।
জেমস মুর

5

আমিও রুবির এক নবাগত এবং একটি হ্যাশ সদৃশ করার ক্ষেত্রেও আমি একই ধরণের সমস্যার মুখোমুখি হয়েছি। নিম্নলিখিত ব্যবহার. এই পদ্ধতির গতি সম্পর্কে আমার কোনও ধারণা নেই।

copy_of_original_hash = Hash.new.merge(original_hash)

3

মার্শাল ডকুমেন্টেশনের সুরক্ষা বিষয়ক বিভাগে উল্লিখিত হিসাবে ,

আপনার যদি অবিশ্বস্ত ডেটা ডিজিটালাইজ করার দরকার হয়, JSON বা অন্য সিরিয়ালাইজেশন ফর্ম্যাটটি ব্যবহার করুন যা কেবল স্ট্রিং, অ্যারে, হ্যাশ ইত্যাদির মতো সহজ, 'আদিম' প্রকার লোড করতে সক্ষম use

এখানে রুবিতে জেএসএন ব্যবহার করে কীভাবে ক্লোনিং করা যায় তার একটি উদাহরণ এখানে দেওয়া হয়েছে:

require "json"

original = {"John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
cloned = JSON.parse(JSON.generate(original))

# Modify original hash
original["John"] << ' Sandler'
p original 
#=> {"John"=>"Adams Sandler", "Thomas"=>"Jefferson", "Johny"=>"Appleseed"}

# cloned remains intact as it was deep copied
p cloned  
#=> {"John"=>"Adams", "Thomas"=>"Jefferson", "Johny"=>"Appleseed"}

1

ব্যবহার Object#clone:

h1 = h0.clone

(Confusingly জন্য ডকুমেন্টেশন cloneবলছেন যে initialize_copyএটিকে ওভাররাইড করার উপায়, কিন্তু যে পদ্ধতি এ জন্য লিঙ্ক Hashআপনার নির্দেশ replaceপরিবর্তে ...)


1

যেহেতু স্ট্যান্ডার্ড ক্লোনিং পদ্ধতি হিমশীতল সংরক্ষণ করে, তাই আপনি যদি নতুন অবজেক্টগুলিকে মূলের চেয়ে কিছুটা আলাদা করতে চান (তবে যদি আপনি রাষ্ট্রবিহীন প্রোগ্রামিং পছন্দ করেন) তবে এটি মূল অবজেক্টের ভিত্তিতে নতুন স্থাবর বস্তু তৈরির জন্য উপযুক্ত নয়।


1

ক্লোন ধীর। পারফরম্যান্সের জন্য সম্ভবত খালি হ্যাশ দিয়ে শুরু করা উচিত এবং মার্জ করা উচিত। নেস্টেড হ্যাশগুলির কেস কভার করে না ...

require 'benchmark'

def bench  Benchmark.bm do |b|    
    test = {'a' => 1, 'b' => 2, 'c' => 3, 4 => 'd'}
    b.report 'clone' do
      1_000_000.times do |i|
        h = test.clone
        h['new'] = 5
      end
    end
    b.report 'merge' do
      1_000_000.times do |i|
        h = {}
        h['new'] = 5
        h.merge! test
      end
    end
    b.report 'inject' do
      1_000_000.times do |i|
        h = test.inject({}) do |n, (k, v)|
          n[k] = v;
          n
        end
        h['new'] = 5
      end
    end
  end
end
  বেঞ্চ ব্যবহারকারী সিস্টেম মোট (বাস্তব)
  ক্লোন 1.960000 0.080000 2.040000 (2.029604)
  মার্জ 1.690000 0.080000 1.770000 (1.767828)
  ইনজেক্ট 3.120000 0.030000 3.150000 (3.152627)
  

1

এটি একটি বিশেষ ক্ষেত্রে তবে আপনি যদি পূর্বনির্ধারিত হ্যাশ দিয়ে শুরু করেন যা আপনি ধরে নিতে এবং তার অনুলিপি তৈরি করতে চান তবে আপনি এমন একটি পদ্ধতি তৈরি করতে পারেন যা একটি হ্যাশ ফেরত দেয়:

def johns 
    {  "John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
end

h1 = johns

আমার যে বিশেষ দৃশ্যটি ছিল তা ছিল আমার কাছে জেএসওএন-স্কিমা হ্যাশগুলির সংকলন ছিল যেখানে কিছু হ্যাশ অন্যদের তৈরি করে others আমি প্রাথমিকভাবে তাদের ক্লাস ভেরিয়েবল হিসাবে সংজ্ঞা দিয়েছিলাম এবং এই অনুলিপিটির ইস্যুতে ছুটে এসেছি।


0

আপনি নীচে হ্যাশ বস্তু অনুলিপি ব্যবহার করতে পারেন।

deeply_copied_hash = Marshal.load(Marshal.dump(original_hash))

16
এটি ওয়েন কনরাডের উত্তরের একটি সদৃশ।
অ্যান্ড্রু গ্রিম

0

যেহেতু রুবীর এটি করার একটি মিলিয়ন উপায় রয়েছে, সুতরাং এখানে গণনার ব্যবহারের আরও একটি উপায় রয়েছে:

h0 = {  "John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
h1 = h0.inject({}) do |new, (name, value)| 
    new[name] = value;
    new 
end

-3

ডিপ_কপির বিকল্প উপায় যা আমার পক্ষে কাজ করেছে।

h1 = {:a => 'foo'} 
h2 = Hash[h1.to_a]

এইচ 2 এর উল্লেখগুলির পরিবর্তে এইচ 1 এর অ্যারে উপস্থাপনা ব্যবহার করে এইচ 2 গঠন হওয়ার কারণে এটি একটি গভীর_কপি তৈরি করেছে।


3
প্রতিশ্রুতিবদ্ধ মনে হচ্ছে তবে কাজ করে না, এটি অন্য অগভীর অনুলিপি
গিন্টি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.