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

การสร้างตัวแจงนับ Ruby ได้ทันที

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

ในสมัยก่อน การกำหนดตัวแจงนับค่อนข้างยุ่งยาก คุณต้องสร้างคลาสใหม่ รวมโมดูลที่นับได้ และกำหนดฟังก์ชัน #each

นับตั้งแต่ Ruby 1.9 เป็นต้นไป เรามีวิธีการระบุตัวแจงนับแบบง่ายๆ ที่เบากว่ามาก มาดูกันเลย

แนะนำคลาส Enumerator

คลาส Enumerator ให้คุณกำหนดตัวแจงนับแบบครั้งเดียว โดยใช้ไวยากรณ์บล็อก ในตัวอย่างด้านล่าง เราสร้างตัวแจงนับที่ส่งคืนชุดตัวเลขสุ่มแบบอนันต์

e = Enumerator.new do |y|
  loop do
    y << rand(10) # The << operator "yields" a value.
  end
end

# Make the enumerator "yield" 10 values, then stop
puts e.first(10).inspect # => [6, 6, 7, 2, 2, 9, 6, 8, 2, 1]

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

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

การหาขนาดของคอลเลกชันทำให้เกิดปัญหาสำหรับผู้แจงนับขี้เกียจของ Ruby ในการนับรายการในคอลเล็กชัน คุณต้องโหลดทั้งคอลเล็กชัน - ซึ่งขัดกับประเด็นทั้งหมดของการใช้ตัวแจงนับขี้เกียจ

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

# You can pass the length as an argument to the constructor, if you have it
e = Enumerator.new(10) do |y|
  10.times { y << rand }
end

ตัวอย่างในชีวิตจริงของฉัน

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

มันค่อนข้างอึดอัดที่จะรู้ว่า <h3> . ตัวไหน แท็กอยู่ในส่วนที่กำหนดโดย <h2> แท็ก คุณต้องแยกวิเคราะห์ HTML โดยใช้ nokogiri แล้วสแกนเอกสารผลลัพธ์ ดังนั้นฉันจึงแยกโค้ดนั้นออกและทำให้เป็นตัวแจงนับ นี่คือลักษณะที่ปรากฏ

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