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

เชี่ยวชาญ Ruby Ranges: การสร้าง การใช้งาน และกลไกภายใน

Range ใน Ruby คืออะไร และทำงานอย่างไร?

Range คือ object ที่มีค่าเริ่มต้นและค่าสิ้นสุด ช่วยสร้าง sequence ที่ครอบคลุมช่วงระหว่างสองค่านี้ คุณสามารถสร้างได้จาก 1 ถึง 20 หรือจาก "a" ถึง "z"

ในบทความนี้คุณจะค้นพบ:

  • วิธีสร้าง Ruby range
  • วิธีใช้เมธอด step และ include? ใน Ruby
  • Range ทำงานภายในอย่างไร

มาเริ่มกัน!

ทำความเข้าใจ Ranges

เพื่อเตือนใจ: syntax ของ Ruby range 長得像這樣:

(1..20)

วงเล็บไม่จำเป็นต้องมีในการกำหนด Range แต่ถ้าคุณต้องการเรียกเมธอดบน range จะต้องมีวงเล็บ มิฉะนั้นคุณจะเรียกเมธอดบน element ตัวที่ 2 ของ range แทนที่จะเป็น range เอง

Class Range include Enumerable ดังนั้นคุณได้เมธอด iteration อันทรงพลังทั้งหมดโดยไม่ต้องแปลง range เป็น array

เมธอด Step ของ Ruby

Range มีเมธอดที่มีประโยชน์ เช่น step:

ตัวอย่าง:

(10..20).step(2).to_a # [10, 12, 14, 16, 18, 20]

ใช้เมธอดนี้เพื่อ iterate ผ่าน range ด้วยการเพิ่มทีละ n โดย n คือ argument ที่ส่งให้ step

วิธีตรวจสอบว่าเลขอยู่ใน Range หรือไม่

เมธอด Range อื่นๆ ที่ควรทราบ: cover? และ include?

จะผิดใหญ่ถ้าคิดว่าทำงานเหมือนกัน เพราะมันไม่เหมือนกันเลย

เมธอด include? ทำตามที่คาดไว้: ตรวจสอบการรวมอยู่ใน range เทียบเท่ากับการขยาย Range เป็น Array แล้วเช็กว่ามีอยู่ไหม

แต่ cover? แตกต่างออกไป มันเพียง ตรวจสอบกับค่าเริ่มต้นและค่าสิ้นสุดของ range (begin <= obj <= end) ซึ่งอาจให้ผลลัพธ์ที่ไมคาดคิด

ตัวอย่าง:

('a'..'z').include? "cc" # false
('a'..'z').cover? "cc" # true

cover? example นี้เทียบเท่ากับ:

"a" <= "cc" && "cc" <= "z"

เหตุผลที่คืนค่า true คือ string ถูกเปรียบเทียบตัวอักษรทีละตัว เนื่องจาก "a" อยู่ก่อน "c" ตัวอักษรหลัง "c" ตัวแรกจึงไม่มีผล

Ranges ถูก implement ใน Ruby อย่างไร

Range ไม่จำกัดแค่ตัวเลขและตัวอักษร คุณสามารถใช้ object ใดๆ ได้ ตราบใดที่มัน implement เมธอดต่อไปนี้: <=> และ succ

เช่น DateTime range:

require 'time'
t1 = DateTime.new
t2 = DateTime.new + 30
next_30_days = t1..t2
# ตัวอย่างการใช้
next_30_days.select(&:friday?).map(&:day)

แล้วมันทำงานอย่างไร? มาดู implementation นี้:

def range(a, b)
  # ถ้า element แรกใหญ่กว่าตัวที่สอง ไม่ใช่ sequential range
  return [] if a > b
  out = []
  # advance จนกว่า element ตัวที่สองจะเท่ากับตัวแรก
  while a != b
    out << a
    a = a.next
  end
  # เพิ่ม element สุดท้าย (inclusive range)
  # นี่ก็คือการ return ผลลัพธ์ผ่าน implicit return
  out << a
end
p range 1, 10
p range 'a', 'z'

ผมเพิ่มคอมเมนต์ช่วยให้เข้าใจง่ายขึ้น แนวคิดคือเราเรียกเมธอด next บน object ตัวแรกซ้ำๆ จนกว่าจะเท่ากับตัวที่สอง โดยสมมติว่ามันจะเจอกันที่สุด

Custom Class Ranges

ส่วนใหญ่คุณจะใช้ number และ character ranges แต่รู้จักวิธีใช้ range ใน custom class ก็ดี

ตัวอย่าง:

class LetterMultiplier
  attr_reader :count
  include Comparable
  def initialize(letter, count)
    @letter = letter
    @count = count
  end
  def succ
    self.class.new(@letter, @count + 1)
  end
  def <=>(other)
    count <=> other.count
  end
end
a = LetterMultiplier.new('w', 2)
b = LetterMultiplier.new('w', 8)
# พิมพ์ array ที่มีทุก item ใน range
p Array(a..b)

หัวใจสำคัญคือ implement <=> และ succ ให้ถูกต้อง ถ้าต้องการใช้ include? ต้อง include module Comparable ซึ่งเพิ่มเมธอดอย่าง ==, <, > (ทั้งหมด based on ผลลัพธ์ของ <=>)

สรุป

ในบทความนี้คุณเรียนรู้ว่า range ทำงานใน Ruby อย่างไร เพื่อให้เข้าใจลึกขึ้นและ implement object ของตัวเองที่รองรับ range operations ได้

อย่าลืมสมัครรับ newsletter ด้านล่างเพื่อไม่พลาดบทความถัดไป 🙂