Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

ตัวแปรวนรอบ (Enumerators) ใน Ruby แบบไดนามิก: คู่มือสร้างแบบ On-the-Fly แบบรวดเร็ว

เมื่อคุณจัดการคอลเล็กชันเป็นตัวแปรวนรอบ (enumerators) คุณจะได้ใช้ฟังก์ชันโปรดอย่าง #map และ #reduce ได้ทันทีโดยไม่ต้องเขียนโค้ดเพิ่มเติม มันสะดวกมาก

รู้จักกับคลาส Enumerator

คลาส Enumerator ช่วยให้คุณสร้างตัวแปรวนรอบแบบใช้ครั้งเดียว (one-off) ด้วยไวยากรณ์บล็อก (block syntax) ตัวอย่างด้านล่างสร้างตัวแปรวนรอบที่คืนค่าลำดับเลขสุ่มแบบไม่มีที่สิ้นสุด

e = Enominator.new do |y|
  loop do
    y << rand(10) # ตัวดำเนินการ << ใช้ "yield" ค่า
  end
end

# ให้ตัวแปรวนรอบ "yield" 10 ค่า แล้วหยุด
puts e.first(10).inspect # => [6, 6, 7, 2, 2, 9, 6, 8, 2, 1]

คุณอาจสังเกตเห็นว่าเราใช้ตัวดำเนินการขยับ << อย่างแปลกประหลาด นี่เป็นทางลัดสำหรับเมธอด y.yield คุณจะเรียกมันสำหรับแต่ละรายการในตัวแปรวนรอบ หากดูเหมือนเวทมนตร์ อย่ากังวล มันจริงๆ แล้วก็เป็นเวทมนตร์จริง

ขนาดของคอลเล็กชัน

การหาขนาดของคอลเล็กชันเป็นปัญหาสำหรับตัวแปรวนรอบแบบ lazy ของ Ruby เพื่อนับจำนวนรายการ คุณต้องโหลดคอลเล็กชันทั้งหมด — ซึ่งขัดกับจุดประสงค์ของการใช้ตัวแปรวนรอบแบบ lazy

มีวิธีแก้ปัญหาบางส่วน: หากคุณรู้ขนาดของคอลเล็กชันตอนสร้าง Enumerator คุณสามารถระบุได้

# สามารถส่งความยาวเป็นอาร์กิวเมนต์ให้ constructor ได้ หากมีข้อมูล
e = Enumerator.new(10) do |y|
  10.times { y << rand }
end

ตัวอย่างการใช้งานจริงของผม

เมื่อวานนี้ผมกำลังทำงานบนเว็บไซต์เอกสารใหม่ของ Honeybadger ซึ่งสร้างด้วย Jekyll ผมเขียนปลั๊กอินเพื่อสร้างสารบัญจากแท็ก <h2> และ <h3> ในเอกสาร

การหาว่าแท็ก <h3> ใดเป็นของส่วนที่ถูกกำหนดโดย <h2> ค่อนข้างยุ่งยาก คุณต้องแยกวิเคราะห์ HTML ด้วย Nokogiri แล้วสแกนเอกสารที่ได้ ผมจึงแยกโค้ส่วนนั้นออกมาและทำให้เป็น Enumerator นี่คือรูปแบบของมัน:

def subheadings(el)
  Enumerator.new do |y|
    next_el = el.next_sibling
    while next_el && next_el.name != "h2"
      if next_el.name == "h3"
        y << next_el
      end
      next_el = next_el.next_sibling
    end
  end
end