Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Iterators

Iterator ประมวลผล collection ทีละ item แบบ lazy (ไม่ทำจนกว่าจะต้องใช้)

🔗 Iterator Chain Visualization

Iterator Chain Diagram


Iterator Trait

pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;

    // ... มี methods อื่นๆ อีกมากที่ได้มาฟรี
}

ทุกครั้งที่เรียก next():

  • Some(item) - ได้ item ถัดไป
  • None - หมดแล้ว

Basic Usage

fn main() {
    let v = vec![1, 2, 3];

    // สร้าง iterator
    let mut iter = v.iter();

    // เรียก next() ทีละครั้ง
    assert_eq!(iter.next(), Some(&1));
    assert_eq!(iter.next(), Some(&2));
    assert_eq!(iter.next(), Some(&3));
    assert_eq!(iter.next(), None);  // หมดแล้ว
    assert_eq!(iter.next(), None);  // ยังคง None
}

3 วิธีสร้าง Iterator

1. iter() - Borrow (&T)

fn main() {
    let v = vec![1, 2, 3];

    for x in v.iter() {
        println!("{}", x);  // x is &i32
    }

    // v ยังใช้ได้
    println!("Still valid: {:?}", v);
}

2. iter_mut() - Mutable Borrow (&mut T)

fn main() {
    let mut v = vec![1, 2, 3];

    for x in v.iter_mut() {
        *x *= 2;  // แก้ไขค่าได้
    }

    println!("{:?}", v);  // [2, 4, 6]
}

3. into_iter() - Take Ownership (T)

fn main() {
    let v = vec![String::from("a"), String::from("b")];

    for s in v.into_iter() {
        println!("{}", s);  // s is String (owned)
    }

    // println!("{:?}", v);  // ❌ v ถูก move ไปแล้ว
}

เปรียบเทียบ

MethodReturnsOwnership
iter()&TBorrow
iter_mut()&mut TMutable borrow
into_iter()TTake ownership

for Loop กับ Iterator

fn main() {
    let v = vec![1, 2, 3];

    // ทั้งสองเหมือนกัน:

    // 1. for loop (syntactic sugar)
    for x in &v {
        println!("{}", x);
    }

    // 2. Explicit iterator
    let mut iter = v.iter();
    while let Some(x) = iter.next() {
        println!("{}", x);
    }
}

Lazy Evaluation

Iterator ไม่ทำอะไรจนกว่าจะ “consume”:

fn main() {
    let v = vec![1, 2, 3];

    // ยังไม่ทำอะไร! (lazy)
    let iter = v.iter().map(|x| {
        println!("Processing {}", x);
        x * 2
    });

    println!("Iterator created, nothing printed yet...");

    // consume iterator
    let result: Vec<_> = iter.collect();
    // NOW it prints "Processing 1, 2, 3"

    println!("Result: {:?}", result);
}

Range as Iterator

fn main() {
    // Range เป็น iterator
    for i in 0..5 {
        println!("{}", i);  // 0, 1, 2, 3, 4
    }

    // Inclusive range
    for i in 0..=5 {
        println!("{}", i);  // 0, 1, 2, 3, 4, 5
    }

    // Use with methods
    let sum: i32 = (1..=100).sum();
    println!("Sum 1-100: {}", sum);  // 5050
}

Common Iterators

fn main() {
    // chars() - iterate characters
    for c in "hello".chars() {
        println!("{}", c);
    }

    // bytes() - iterate bytes
    for b in "hello".bytes() {
        println!("{}", b);
    }

    // lines() - iterate lines
    let text = "line1\nline2\nline3";
    for line in text.lines() {
        println!("{}", line);
    }

    // enumerate() - with index
    let v = vec!["a", "b", "c"];
    for (i, x) in v.iter().enumerate() {
        println!("{}: {}", i, x);
    }
}

Infinite Iterators

fn main() {
    // repeat - ซ้ำค่าเดิมตลอด
    let threes: Vec<i32> = std::iter::repeat(3).take(5).collect();
    println!("{:?}", threes);  // [3, 3, 3, 3, 3]

    // cycle - วนซ้ำ
    let cycle: Vec<i32> = vec![1, 2].into_iter().cycle().take(6).collect();
    println!("{:?}", cycle);  // [1, 2, 1, 2, 1, 2]
}

ลองทำดู! 🎯

  1. ใช้ iter(), iter_mut(), into_iter() ดูความแตกต่าง
  2. สร้าง range iterator และ sum
  3. ใช้ enumerate() กับ vector

สรุป

ConceptDescription
Iterator traitnext() -> Option<Item>
iter()Borrow elements
iter_mut()Mutable borrow
into_iter()Take ownership
Lazyไม่ทำจนกว่า consume
Infiniterepeat, cycle

👉 ต่อไป: Iterator Methods