Rust Iterator ์ธํฐํ์ด์ค ์ข ํฉ
1. ํต์ฌ ํธ๋ ์ดํธ
Iterator ํธ๋ ์ดํธ
pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    // ... ์ฌ๋ฌ ๊ธฐ๋ณธ ๊ตฌํ ๋ฉ์๋๋ค
}
IntoIterator ํธ๋ ์ดํธ
pub trait IntoIterator {
    type Item;
    type IntoIter: Iterator<Item = Self::Item>;
    fn into_iter(self) -> Self::IntoIter;
}
FromIterator ํธ๋ ์ดํธ
pub trait FromIterator<A> {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = A>;
}
2. ๋ฐ๋ณต์ ์์ฑ ๋ฉ์๋
๊ธฐ๋ณธ ์ปฌ๋ ์  ๋ฐ๋ณต์
iter(): ๋ถ๋ณ ์ฐธ์กฐ ๋ฐ๋ณต์ (&T)iter_mut(): ๊ฐ๋ณ ์ฐธ์กฐ ๋ฐ๋ณต์ (&mut T)into_iter(): ์์ ๊ถ ์ด์  ๋ฐ๋ณต์ (T)
๋ฒ์ ๋ฐ๋ณต์
// ๋ฒ์ ๋ฌธ๋ฒ์ผ๋ก ๋ฐ๋ณต์ ์์ฑ
let range = 1..5;        // 1, 2, 3, 4
let inclusive = 1..=5;   // 1, 2, 3, 4, 5
์คํธ๋ฆผ ๋ฐ๋ณต์
std::io::Lines: ํ์ผ์ ๊ฐ ์ค์ ์ํstd::io::Bytes: ๋ฐ์ดํธ ์คํธ๋ฆผ์ ์ํ
๊ธฐํ ๋ฐ๋ณต์ ์์ฑ
once: ๋จ์ผ ๊ฐ์ ์์ฑํ๋ ๋ฐ๋ณต์
use std::iter;
let once = iter::once(42);  // 42๋ง ์์ฑ
repeat: ๋์ผํ ๊ฐ์ ๋ฌดํํ ์์ฑํ๋ ๋ฐ๋ณต์
let repeat = iter::repeat('a');  // 'a'๋ฅผ ๋ฌดํํ ์์ฑ
empty: ๋น ๋ฐ๋ณต์
let empty: iter::Empty<i32> = iter::empty();  // ํญ๋ชฉ ์์
3. ๋ฐ๋ณต์ ์ด๋ํฐ ๋ฉ์๋ (์์ฃผ ์ฌ์ฉ๋๋ ๊ฒ๋ค)
ํํฐ๋ง ์ด๋ํฐ
filter(pred): ์กฐ๊ฑด์ ๋ง์กฑํ๋ ํญ๋ชฉ๋ง ์ ์งfilter_map(f): ๋ณํ๊ณผ ํํฐ๋ง์ ๋์์ ์ํtake(n): ์ฒ์ n๊ฐ ํญ๋ชฉ๋ง ์ ์งtake_while(pred): ์กฐ๊ฑด์ด ์ฐธ์ธ ๋์์ ํญ๋ชฉ๋ง ์ ์งskip(n): ์ฒ์ n๊ฐ ํญ๋ชฉ์ ๊ฑด๋๋skip_while(pred): ์กฐ๊ฑด์ด ์ฐธ์ธ ๋์ ํญ๋ชฉ์ ๊ฑด๋๋step_by(n): n ๋จ๊ณ๋ง๋ค ํญ๋ชฉ์ ์ ํpeekable(): ๋ค์ ํญ๋ชฉ์ ๋ฏธ๋ฆฌ ํ์ธํ ์ ์๋ ๋ฐ๋ณต์ ์์ฑ
๋ณํ ์ด๋ํฐ
map(f): ๊ฐ ํญ๋ชฉ์ ๋ณํflat_map(f): ์ค์ฒฉ ๋ฐ๋ณต์๋ฅผ ํํํflatten(): ์ค์ฒฉ๋ ๋ฐ๋ณต์๋ฅผ ํ ์์ค ํํํinspect(f): ๊ฐ ํญ๋ชฉ์ ๊ฒ์ฌ (๋๋ฒ๊น ์ฉ)cloned(): ์ฐธ์กฐ ๋ฐ๋ณต์์ ๊ฐ์ ๋ณต์ copied(): ๋ณต์ฌ ๊ฐ๋ฅํ ์ฐธ์กฐ ๋ฐ๋ณต์์ ๊ฐ์ ๋ณต์ฌmap_while(f): ์กฐ๊ฑด์ด ์ฐธ์ธ ๋์ ๋ณํscan(state, f): ์ํ๋ฅผ ๊ฐ์ง ๋ณํ
๊ฒฐํฉ ์ด๋ํฐ
chain(other): ๋ ๋ฐ๋ณต์๋ฅผ ์ฐ๊ฒฐzip(other): ๋ ๋ฐ๋ณต์๋ฅผ ์์ผ๋ก ๊ฒฐํฉunzip(): ์์ ๋ฐ๋ณต์๋ฅผ ๋ ๊ฐ๋ก ๋ถ๋ฆฌenumerate(): ์ธ๋ฑ์ค์ ๊ฐ์ ์์ผ๋ก ๋ณํpartition(pred): ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ ๊ทธ๋ฃน์ผ๋ก ๋ถ๋ฆฌ
์์ ๊ด๋ จ ์ด๋ํฐ
rev(): ๋ฐ๋ณต์์ ์์๋ฅผ ๋ค์ง์ (์๋ฐฉํฅ ๋ฐ๋ณต์์๋ง ์ ์ฉ ๊ฐ๋ฅ)cycle(): ๋ฐ๋ณต์๋ฅผ ๋ฌดํํ ๋ฐ๋ณตinterleave(other): ๋ ๋ฐ๋ณต์์ ํญ๋ชฉ์ ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์์ฑinterleave_shortest(other): ๋ ์งง์ ๋ฐ๋ณต์๊น์ง๋ง ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์์ฑ
๊ทธ๋ฃนํ ์ด๋ํฐ
chunks(n): n๊ฐ ํญ๋ชฉ์ ์ฒญํฌ๋ก ๊ทธ๋ฃนํchunks_exact(n): ์ ํํ n๊ฐ ํญ๋ชฉ์ ์ฒญํฌ๋ก ๊ทธ๋ฃนํwindows(n): n๊ฐ ํญ๋ชฉ์ ์ฌ๋ผ์ด๋ฉ ์๋์ฐ๋ก ๊ทธ๋ฃนํ
4. ๋ฐ๋ณต์ ์๋น์ ๋ฉ์๋
์ปฌ๋ ์  ๋ณํ
collect(): ๋ฐ๋ณต์๋ฅผ ์ปฌ๋ ์ ์ผ๋ก ๋ณํ
let v: Vec<i32> = (0..5).collect();
let s: HashSet<i32> = (0..5).collect();
let m: HashMap<char, i32> = vec![('a', 1), ('b', 2)].into_iter().collect();
๊ณ์ฐ ์๋น์
sum(): ๋ชจ๋ ํญ๋ชฉ์ ํฉ๊ณ๋ฅผ ๊ณ์ฐproduct(): ๋ชจ๋ ํญ๋ชฉ์ ๊ณฑ์ ๊ณ์ฐfold(init, f): ์ด๊ธฐ๊ฐ๊ณผ ํจ์๋ก ๋ชจ๋ ํญ๋ชฉ์ ์ ์reduce(f): ์ฒซ ํญ๋ชฉ์ ์ด๊ธฐ๊ฐ์ผ๋ก ์ฌ์ฉํ์ฌ ์ ์try_fold(init, f): ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ foldtry_reduce(f): ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ reduce
๊ฒ์ ์๋น์
find(pred): ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ฒซ ํญ๋ชฉ์ ์ฐพ์position(pred): ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ฒซ ํญ๋ชฉ์ ์์น๋ฅผ ์ฐพ์rposition(pred): ๋ค์์๋ถํฐ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ฒซ ํญ๋ชฉ์ ์์น๋ฅผ ์ฐพ์contains(&x): ํน์  ํญ๋ชฉ์ ํฌํจํ๋์ง ํ์ธany(pred): ์กฐ๊ฑด์ ๋ง์กฑํ๋ ํญ๋ชฉ์ด ์๋์ง ํ์ธall(pred): ๋ชจ๋ ํญ๋ชฉ์ด ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ํ์ธmax(): ์ต๋ ํญ๋ชฉ์ ์ฐพ์min(): ์ต์ ํญ๋ชฉ์ ์ฐพ์max_by(cmp): ๋น๊ต ํจ์๋ก ์ต๋ ํญ๋ชฉ์ ์ฐพ์min_by(cmp): ๋น๊ต ํจ์๋ก ์ต์ ํญ๋ชฉ์ ์ฐพ์max_by_key(f): ํค ํจ์๋ก ์ต๋ ํญ๋ชฉ์ ์ฐพ์min_by_key(f): ํค ํจ์๋ก ์ต์ ํญ๋ชฉ์ ์ฐพ์
๊ธฐํ ์๋น์
count(): ํญ๋ชฉ์ ์๋ฅผ ๋ฐํlast(): ๋ง์ง๋ง ํญ๋ชฉ์ ๋ฐํnth(n): n๋ฒ์งธ ํญ๋ชฉ์ ๋ฐํfor_each(f): ๊ฐ ํญ๋ชฉ์ ํจ์๋ฅผ ์ ์ฉtry_for_each(f): ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ for_eachis_partitioned(pred): ๋ฐ๋ณต์๊ฐ ๋ถํ ๋์ด ์๋์ง ํ์ธis_sorted(): ๋ฐ๋ณต์๊ฐ ์ ๋ ฌ๋์ด ์๋์ง ํ์ธis_sorted_by(cmp): ๋น๊ต ํจ์๋ก ์ ๋ ฌ ์ฌ๋ถ ํ์ธ
5. ํน์ ๋ฐ๋ณต์ ์ ํ
Peekable
๋ค์ ํญ๋ชฉ์ ์๋นํ์ง ์๊ณ ๋ฏธ๋ฆฌ ํ์ธํ ์ ์๋ ๋ฐ๋ณต์:
let mut peekable = [1, 2, 3].iter().peekable();
if let Some(&first) = peekable.peek() {
    println!("๋ค์ ํญ๋ชฉ: {}", first);
}
Fuse
None์ ๋ฐํํ ์ดํ ํญ์ None์ ๋ฐํํ๋๋ก ๋ณด์ฅํ๋ ๋ฐ๋ณต์:
let fused = [1, 2, 3].iter().fuse();
Cycle
๋ฐ๋ณต์๋ฅผ ๋ฌดํํ ๋ฐ๋ณตํ๋ ๋ฐ๋ณต์:
let mut cycle = [1, 2, 3].iter().cycle();
// 1, 2, 3, 1, 2, 3, ...
Enumerate
์ธ๋ฑ์ค์ ๊ฐ์ ์์ผ๋ก ์์ฑํ๋ ๋ฐ๋ณต์:
let enumerated = ['a', 'b', 'c'].iter().enumerate();
// (0, 'a'), (1, 'b'), (2, 'c')
Chain
๋ ๋ฐ๋ณต์๋ฅผ ์ฐ๊ฒฐํ๋ ๋ฐ๋ณต์:
let chained = [1, 2].iter().chain([3, 4].iter());
// 1, 2, 3, 4
Zip
๋ ๋ฐ๋ณต์๋ฅผ ์์ผ๋ก ๋ฌถ๋ ๋ฐ๋ณต์:
let zipped = [1, 2].iter().zip(['a', 'b'].iter());
// (1, 'a'), (2, 'b')
6. ๊ตฌํ ํจํด
์ปฌ๋ ์ ์ ๋ฐ๋ณต์ ๊ตฌํํ๊ธฐ
struct MyCollection<T> {
    data: Vec<T>,
}
impl<T> MyCollection<T> {
    fn iter(&self) -> impl Iterator<Item = &T> {
        self.data.iter()
    }
    
    fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        self.data.iter_mut()
    }
}
impl<T> IntoIterator for MyCollection<T> {
    type Item = T;
    type IntoIter = std::vec::IntoIter<T>;
    
    fn into_iter(self) -> Self::IntoIter {
        self.data.into_iter()
    }
}
impl<'a, T> IntoIterator for &'a MyCollection<T> {
    type Item = &'a T;
    type IntoIter = std::slice::Iter<'a, T>;
    
    fn into_iter(self) -> Self::IntoIter {
        self.data.iter()
    }
}
impl<'a, T> IntoIterator for &'a mut MyCollection<T> {
    type Item = &'a mut T;
    type IntoIter = std::slice::IterMut<'a, T>;
    
    fn into_iter(self) -> Self::IntoIter {
        self.data.iter_mut()
    }
}
์ฌ์ฉ์ ์ ์ ๋ฐ๋ณต์ ๊ตฌํํ๊ธฐ
struct Fibonacci {
    curr: u32,
    next: u32,
}
impl Fibonacci {
    fn new() -> Fibonacci {
        Fibonacci { curr: 0, next: 1 }
    }
}
impl Iterator for Fibonacci {
    type Item = u32;
    
    fn next(&mut self) -> Option<Self::Item> {
        let new_next = self.curr + self.next;
        self.curr = self.next;
        self.next = new_next;
        Some(self.curr)
    }
}
7. ์ ์ฉํ ํจํด๊ณผ ๊ธฐ๋ฒ
์ปฌ๋ ์  ๋ณํํ๊ธฐ
// Vec<T> -> Vec<U>
let v: Vec<i32> = vec![1, 2, 3];
let doubled: Vec<i32> = v.iter().map(|&x| x * 2).collect();
// Vec<T> -> HashSet<T>
let set: HashSet<i32> = v.iter().cloned().collect();
// Vec<T> -> HashMap<K, V>
let map: HashMap<i32, char> = vec![(1, 'a'), (2, 'b')].into_iter().collect();
๊ทธ๋ฃนํ ๋ฐ ํํฐ๋ง
// ์ง์์ ํ์๋ก ๊ทธ๋ฃนํ
let (even, odd): (Vec<i32>, Vec<i32>) = (1..=10).partition(|&n| n % 2 == 0);
// ์กฐ๊ฑด์ ๋ฐ๋ผ ํํฐ๋ง
let positive: Vec<i32> = vec![-1, 2, -3, 4].into_iter().filter(|&x| x > 0).collect();
Result์ ํจ๊ป ์ฌ์ฉํ๊ธฐ
// ๋ชจ๋  ๊ฒฐ๊ณผ๊ฐ Ok์ธ์ง ํ์ธ
let results = vec![Ok(1), Ok(2), Ok(3)];
let all_ok = results.iter().all(|r| r.is_ok());
// Ok ๊ฐ๋ง ์์ง
let ok_values: Vec<i32> = results.into_iter().filter_map(Result::ok).collect();
Option๊ณผ ํจ๊ป ์ฌ์ฉํ๊ธฐ
// Some ๊ฐ๋ง ์์ง
let options = vec![Some(1), None, Some(2)];
let values: Vec<i32> = options.into_iter().filter_map(|o| o).collect();
์ค์ฒฉ ๊ตฌ์กฐ ์ฒ๋ฆฌํ๊ธฐ
// ์ค์ฒฉ ๋ฐ๋ณต์ ํํํ
let nested = vec![vec![1, 2], vec![3, 4]];
let flat: Vec<i32> = nested.into_iter().flatten().collect();  // [1, 2, 3, 4]
// map๊ณผ flatten ์กฐํฉ
let words = vec!["hello", "world"];
let chars: Vec<char> = words.iter()
    .flat_map(|word| word.chars())
    .collect();  // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
์์ฐจ ์ฒ๋ฆฌ vs ๋ณ๋ ฌ ์ฒ๋ฆฌ
// ์์ฐจ ์ฒ๋ฆฌ (ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ)
let sum: i32 = (1..1000).sum();
// ๋ณ๋ ฌ ์ฒ๋ฆฌ (rayon ํฌ๋ ์ดํธ ์ฌ์ฉ)
use rayon::prelude::*;
let sum: i32 = (1..1000).into_par_iter().sum();
๋ฌดํ ๋ฐ๋ณต์ ๋ค๋ฃจ๊ธฐ
// ๋ฌดํ ๋ฐ๋ณต์ ์์ฑ
let infinite = std::iter::repeat(1);
// ์ ํ ๋ฐ๋ณต์๋ก ์ ํ
let finite: Vec<i32> = infinite.take(5).collect();  // [1, 1, 1, 1, 1]
8. ์ธ๋ถ ํฌ๋ ์ดํธ์ ๋ฐ๋ณต์ ํ์ฅ
Itertools ํฌ๋ ์ดํธ
Itertools๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฐ๋ณต์ ๊ธฐ๋ฅ์ ํ์ฅ:
use itertools::Itertools;
// ๊ทธ๋ฃนํ
let groups = vec![1, 1, 1, 3, 3, 2, 2, 2]
    .into_iter()
    .group_by(|&x| x);
// ์์ด
let permutations = [1, 2, 3].iter().permutations(2);
// ์กฐํฉ
let combinations = [1, 2, 3, 4].iter().combinations(2);
// intersperse
let interspersed: Vec<i32> = [1, 2, 3].iter()
    .cloned()
    .intersperse(0)
    .collect();  // [1, 0, 2, 0, 3]
// ์ค๋ณต ํญ๋ชฉ ์ ๊ฑฐ
let unique: Vec<i32> = [1, 2, 1, 3, 2].iter()
    .cloned()
    .unique()
    .collect();  // [1, 2, 3]
Rayon ํฌ๋ ์ดํธ
Rayon์ ๋ณ๋ ฌ ๋ฐ๋ณต์ ์ ๊ณต:
use rayon::prelude::*;
// ๋ณ๋ ฌ ๋งต
let v: Vec<i32> = (0..1000)
    .into_par_iter()
    .map(|i| i * i)
    .collect();
// ๋ณ๋ ฌ ํํฐ
let evens: Vec<i32> = (0..1000)
    .into_par_iter()
    .filter(|i| i % 2 == 0)
    .collect();