لماذا يونيك! العودة لا شيء إذا لم يكن هناك تكرارات
سؤال
لقد بدأت للتو مع روبي وأجد شخصياً أن ما يلي بمثابة انتهاك لـ "مبدأ أقل مفاجأة". وهذا هو ، نقلاً عن وثائق, ، هذا UNIQ! "يزيل العناصر المكررة من الذات. إرجاع لا شيء إذا لم يتم إجراء أي تغييرات (أي أنه لم يتم العثور على التكرارات)."
هل يمكن لأي شخص أن يشرح هذا ، والذي يبدو أنه معاكس تمامًا بالنسبة لي؟ هذا يعني أنه بدلاً من أن تكون قادرًا على كتابة سطر واحد من التعليمات البرمجية أدناه عن طريق إلحاق. uniq! لإنهاء السطر الأول ، بدلاً من ذلك يجب أن أكتب الخطين التاليين:
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks = hooks.uniq
أم أفتقد شيئًا ما ، طريقة أفضل؟
تعديل:
أنا أفهم ذلك Uniq! يعدل المعامل. إليك المشكلة الموضحة بشكل أفضل وآمل:
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
puts hooks.length #50
puts hooks.uniq!.length #undefined method `length' for nil:NilClass
أنا أزعم أن الطريقة Uniq! الأعمال تجعلها بلا معنى وعديمة الفائدة. بالتأكيد في حالتي كما أشرت ، يمكنني فقط إلحاق. uniq إلى السطر الأول. ولكن في وقت لاحق في نفس البرنامج ، أدفع العناصر إلى صفيف آخر داخل حلقة. بعد ذلك ، تحت الحلقة ، أود أن "DEPE" الصفيف ، لكنني لا أجرؤ على كتابة "Hooks_tested.uniq!" لأنه يمكن أن يعود لا شيء. بدلا من ذلك أنا يجب اكتب hooks_tested = hooks_tested.uniq
في الواقع ، أنا أؤكد أن هذا هو سوء استخدام فظيع بشكل خاص من حيث أنه من المبدأ المعروف أنه عند وضع طريقة تُرجع صفيفًا ، يجب على المرء دائمًا إعادة صفيف فارغ على الأقل ، بدلاً من لا شيء
المحلول
هذا بسبب uniq!
تعديل self
و إذا uniq!
سيعود قيمة لن تتمكن من معرفة ما إذا كان التغيير قد حدث بالفعل في الكائن الأصلي.
var = %w(green green yellow)
if var.uniq!
# the array contained duplicate entries
else
# nothing changed
end
في الكود الخاص بك يمكنك ببساطة الكتابة
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks.uniq!
# here hooks is already changed
إذا كنت بحاجة إلى إرجاع قيمة الخطاف ربما لأن عبارة الطريقة الأخيرة تفعل فقط
def method
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks.uniq
end
او غير ذلك
def method
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks.uniq!
hooks
end
نصائح أخرى
تعجب نقطة التعجب uniq!
يشير إلى أنه يعدل المصفوفة بدلاً من إعادة واحدة جديدة. يجب علبك ان تفعل ذلك:
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).uniq
أو هذا
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)
hooks.uniq!
puts hooks.length
يمكنك إلحاق uniq
(لا توجد علامة تعجب في النهاية) حتى نهاية السطر الأول.
أو ، إذا أصرت على استخدام uniq!
, ، استعمال
(hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/)).uniq!
هذه ليست إجابة على السبب ، بل حل بديل.
حيث uniq
لا يعود nil
, ، أنا أستعمل uniq
وتعيين النتيجة إلى متغير جديد بدلاً من استخدام إصدار الانفجار
original = [1,2,3,4]
new = original.uniq
#=> new is [1,2,3,4]
#=> ... rather than nil
وجود متغير جديد هو سعر صغير للدفع. من المؤكد أن الجحيم يدق إذا كان الشيكات ، مع مكالمات معقدة متكررة uniq!
و uniq
والتحقق من nil
منذ روبي 1.9 ، Object#tap
متاح:
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).tap do |hooks|
hooks.uniq!
end
puts hooks.length
وربما أكثر إيجازًا (H/Taetherus):
hooks = IO.read(wt_hooks_impl_file).scan(/wt_rt_00\w{2}/).tap(&:uniq!)
puts hooks.length