لماذا يونيك! العودة لا شيء إذا لم يكن هناك تكرارات

StackOverflow https://stackoverflow.com/questions/2102252

  •  21-09-2019
  •  | 
  •  

سؤال

لقد بدأت للتو مع روبي وأجد شخصياً أن ما يلي بمثابة انتهاك لـ "مبدأ أقل مفاجأة". وهذا هو ، نقلاً عن وثائق, ، هذا 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top