Ruby Array วัตถุ find_first?


137

ฉันขาดอะไรบางอย่างในเอกสาร Array หรือไม่ ฉันมีอาร์เรย์ที่มีออบเจ็กต์มากถึงหนึ่งชิ้นที่ตรงตามเกณฑ์ที่กำหนด ฉันต้องการค้นหาวัตถุนั้นอย่างมีประสิทธิภาพ ความคิดที่ดีที่สุดที่ฉันมีจากเอกสารคือ:

candidates = my_array.select { |e| e.satisfies_condition? }
found_it = candidates.first if !candidates.empty?

แต่ฉันไม่พอใจด้วยเหตุผลสองประการ:

  1. นั่นselectทำให้ฉันสำรวจอาร์เรย์ทั้งหมดแม้ว่าเราจะสามารถประกันตัวได้หลังจากการโจมตีครั้งแรก
  2. ฉันต้องการรหัสบรรทัด (พร้อมเงื่อนไข) เพื่อทำให้ผู้สมัครแบนราบ

การดำเนินการทั้งสองอย่างสิ้นเปลืองโดยรู้ล่วงหน้าว่ามีวัตถุที่น่าพอใจ 0 หรือ 1 ชิ้น

สิ่งที่ฉันต้องการคือ:

array.find_first(block)

ซึ่งส่งคืนค่า nil หรืออ็อบเจ็กต์แรกที่บล็อกประเมินเป็น true โดยสิ้นสุดการข้ามผ่านที่อ็อบเจ็กต์นั้น

ฉันต้องเขียนเองหรือไม่? วิธีการที่ยอดเยี่ยมอื่น ๆ ทั้งหมดใน Array ทำให้ฉันคิดว่ามันอยู่ที่นั่นและฉันไม่เห็นมัน

คำตอบ:


206

ฉันไม่เข้าใจคำถามของคุณหรือEnumerable # findคือสิ่งที่คุณกำลังมองหา


32
ไม่มีปัญหาฉันมักพบว่าน่ารำคาญที่เอกสารทับทิมไม่ได้แสดงวิธีการของคลาสและโมดูลที่สืบทอดหรือรวมทั้งหมด
Mladen Jablanović

4
ข้อมูลเพิ่มเติม: [1,2,3,5,2].find { |n| puts n; n == 2 } การวนซ้ำจะหยุดเมื่อพบองค์ประกอบแรกที่ตรงกัน
rajuGT

98

ใช้detectวิธีอาร์เรย์หากคุณต้องการส่งคืนค่าแรกโดยที่บล็อกส่งคืนจริง

[1,2,3,11,34].detect(&:even?) #=> 2

OR

[1,2,3,11,34].detect{|i| i.even?} #=> 2

หากคุณต้องการส่งคืนค่าทั้งหมดโดยที่ block ส่งคืนค่าจริงให้ใช้ select

[1,2,3,11,34].select(&:even?)  #=> [2, 34]

5
.detectคือสิ่งที่ฉันต้องการ แต่ตอนนั้นต่างกัน.findอย่างไร?
Augustin Riedinger

13
@AugustinRiedinger ไม่แตกต่างทั้งคู่เหมือนกัน detectเป็นเพียงนามแฝงของfind ruby-doc.org/core-2.1.2/Enumerable.html#method-i-find
Sandip Ransing

เพื่อความสอดคล้องบางอย่างฉันชอบทำตามThe Ruby Style Guideซึ่งชื่นชอบ
Paul van Leeuwen

20

เดาว่าคุณพลาดวิธีการค้นหาในเอกสาร:

my_array.find {|e| e.satisfies_condition? }

8
หรือถ้าคุณชอบตีกอล์ฟmy_array.find(&:satisfies_condition?)
Andrew Grimm

14

คุณไม่จำเป็นต้องวัตถุเองหรือไม่หรือคุณเพียงแค่ต้องทราบว่ามีเป็นวัตถุที่น่าพอใจ ถ้าก่อนหน้านี้ใช่: ใช้ค้นหา:

found_object = my_array.find { |e| e.satisfies_condition? }

มิฉะนั้นคุณสามารถใช้ any?

found_it = my_array.any?  { |e| e.satisfies_condition? }

หลังจะประกันตัวด้วย "จริง" เมื่อพบสิ่งที่ตรงตามเงื่อนไข เดิมจะทำเช่นเดียวกัน แต่กลับวัตถุ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.