تكرار مجموعة من الأوتار
سؤال
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"]
وسوف يعمل فقط لمصفوفات مستوى واحد