سؤال

arr = ["red","green","yellow"]

arr2 = arr.clone
arr2[0].replace("blue")

puts arr.inspect
puts arr2.inspect

ينتج عنه:

["blue", "green", "yellow"]
["blue", "green", "yellow"]

هل هناك على أي حال للقيام بنسخة عميقة من مجموعة من الأوتار ، بخلاف استخدام المارشال كما أفهم أنه اختراق.

بإمكاني عمل:

arr2 = []
arr.each do |e|
  arr2 << e.clone
end

لكنها لا تبدو أنيقة للغاية أو فعالة.

شكرًا

هل كانت مفيدة؟

المحلول

يمكن تقصير الحل الثاني إلى arr2 = arr.map do |e| e.dup end (ما لم تكن بحاجة فعلاً إلى سلوك clone, ، يوصى باستخدامه dup في حين أن).

بخلاف أن حلينك هما الحلول القياسية لأداء نسخة عميقة (على الرغم من أن الإصدار الثاني هو فقط على مستوى واحد (أي إذا كنت تستخدمه في مجموعة من صفائف الأوتار ، فلا يزال بإمكانك تحوير الأوتار)). لا يوجد حقًا طريقة أجمل.

تحرير: إليك طريقة Deep_dup متكررة تعمل مع صفائف متداخلة بشكل تعسفي:

class Array
  def deep_dup
    map {|x| x.deep_dup}
  end
end

class Object
  def deep_dup
    dup
  end
end

class Numeric
  # We need this because number.dup throws an exception
  # We also need the same definition for Symbol, TrueClass and FalseClass
  def deep_dup
    self
  end
end

قد ترغب أيضًا في تحديد deep_dup للحاويات الأخرى (مثل التجزئة) ، وإلا ستحصل على نسخة ضحلة لهؤلاء.

نصائح أخرى

أوصي بفكرتك الأولية ، ولكن كتبت بشكل أكثر بقليل:

arr = ["red","green","yellow"]
arr2 = arr.inject([]) { |a,element| a << element.dup }

أنا في وضع مماثل وقلق كبير بشأن السرعة. كانت أسرع طريقة بالنسبة لي هي الاستفادة map{&:clone}

لذا جرب هذا:

pry(main)> a = (10000..1000000).to_a.shuffle.map(&:to_s)
pry(main)> Benchmark.ms { b = a.deep_dup }                                                                                     
=> 660.7760030310601
pry(main)> Benchmark.ms { b = a.join("--!--").split("--!--") }
=> 605.0828141160309
pry(main)> Benchmark.ms { b = a.map(&:clone) }
=> 450.8283680770546

يمكنك عمل نسخة عميقة من المصفوفة a عن طريق الكود التالي:

 Marshal.load(Marshal.dump(a))

يبدو بسيطًا جدًا .. فقط قم بتشغيل الرمز أدناه:

a = [1,2,3]
b = [].replace(a)

b[1] = 5

puts a
puts b

تشغيل الرمز أعلاه وسوف تلاحظ الفرق. هتافات !

يمكنك استخدام هذا الاختراق:

arr1 = %w{ red green blue }
arr2 = arr1.join("--!--").split("--!--")

لكنه فقط من أجل المتعة :)

arr2[0].replace("lol")
p arr1
#=> ["red", "green", "blue"]
p arr2
#=> ["lol", "green", "blue"]

وسوف يعمل فقط لمصفوفات مستوى واحد

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top