Custom Iterators बनाना
In this page:
struct Name {
state: Type,
}
impl Iterator for Name {
type Item = Type;
fn next(&mut self) -> Option<Type> {
// return Some(value) or None
}
}
A Custom Iterator Struct
एक custom iterator आमतौर पर एक छोटा struct होता है जो अगला item compute करने के लिए ज़रूरी किसी भी state को रखता है, इसके ऊपर Iterator implemented होने के साथ।
उदाहरण: A Custom Iterator Struct
// Define a struct `Evens` to group related fields together
struct Evens {
current: i32,
max: i32,
}
// Implement the `Iterator` trait for `Evens`
impl Iterator for Evens {
type Item = i32;
// Define the function `next` taking `self` and returning a `Option<i32>`
fn next(&mut self) -> Option<i32> {
// Check whether `self.current > self.max`
if self.current > self.max {
None
// Otherwise, run this branch
} else {
// Declare an immutable variable `value`, set to `self.current`
let value = self.current;
self.current += 2;
Some(value)
}
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `evens`, set to `Evens { current: 0, max: 8 }`
let evens = Evens { current: 0, max: 8 };
// Loop over `evens`, binding each item to `n`
for n in evens {
// Print "{}" to the console, substituting in `n` (with a trailing newline)
println!("{}", n);
}
}
Login to try C/C++/Java/PHP code in the editor
Using Adapters on a Custom Iterator
एक बार Iterator implement हो जाए, एक custom type अपने आप adapter methods की पूरी range support करता है, आपको बिल्कुल वैसे ही pipelines बनाने देते हुए जैसे आप एक built-in iterator पर बनाते।
उदाहरण: Using Adapters on a Custom Iterator
// Define a struct `Evens` to group related fields together
struct Evens {
current: i32,
max: i32,
}
// Implement the `Iterator` trait for `Evens`
impl Iterator for Evens {
type Item = i32;
// Define the function `next` taking `self` and returning a `Option<i32>`
fn next(&mut self) -> Option<i32> {
// Check whether `self.current > self.max`
if self.current > self.max {
None
// Otherwise, run this branch
} else {
// Declare an immutable variable `value`, set to `self.current`
let value = self.current;
self.current += 2;
Some(value)
}
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `total` (an integer), set to `Evens { current: 0, max: 10 }.map(|n| n * 2).sum()`
let total: i32 = Evens { current: 0, max: 10 }.map(|n| n * 2).sum();
// Print "Total: {}" to the console, substituting in `total` (with a trailing newline)
println!("Total: {}", total);
}
Login to try C/C++/Java/PHP code in the editor
Implementing IntoIterator for a Collection
किसी custom collection struct के लिए IntoIterator implement करना इसे सीधे एक for loop के साथ उपयोग होने देता है, एक inner iterator type को delegate करते हुए।
उदाहरण: Implementing IntoIterator for a Collection
// Define a struct `Bag` to group related fields together
struct Bag {
items: Vec<i32>,
}
// Implement the `IntoIterator` trait for `Bag`
impl IntoIterator for Bag {
type Item = i32;
type IntoIter = std::vec::IntoIter<i32>;
// Define the function `into_iter` taking `self` and returning a `Self::IntoIter`
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `bag`, set to `Bag { items: vec![10, 20, 30] }`
let bag = Bag { items: vec![10, 20, 30] };
// Loop over `bag`, binding each item to `item`
for item in bag {
// Print "{}" to the console, substituting in `item` (with a trailing newline)
println!("{}", item);
}
}
Login to try C/C++/Java/PHP code in the editor
Ensuring the Iterator Terminates
एक सही implemented iterator को आखिरकार None return करना चाहिए; नहीं तो, इसे पूरी तरह consume करने वाला कोई भी code (जैसे .collect() या .sum()) हमेशा के लिए loop करेगा।
उदाहरण: Ensuring the Iterator Terminates
// Define a struct `Countdown` to group related fields together
struct Countdown(u32);
// Implement the `Iterator` trait for `Countdown`
impl Iterator for Countdown {
type Item = u32;
// Define the function `next` taking `self` and returning a `Option<u32>`
fn next(&mut self) -> Option<u32> {
// Check whether `self.0 == 0`
if self.0 == 0 {
None
// Otherwise, run this branch
} else {
self.0 -= 1;
Some(self.0 + 1)
}
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `collected` (a `Vec<u32>`), set to `Countdown(5).collect()`
let collected: Vec<u32> = Countdown(5).collect();
// Print "{:?}" to the console, substituting in `collected` (with a trailing newline)
println!("{:?}", collected);
}
Login to try C/C++/Java/PHP code in the editor
- किसी collection struct के लिए
IntoIteratorimplement करना भूल जाना अगर आप चाहते हैं कि यह सीधे एकforloop में काम करे। next()को इस तरह लिखना जो कभीNonereturn नहीं करता,.collect()जैसे किसी consuming method को हमेशा के लिए loop करने का कारण बनते हुए।- Common adapter logic को manually फिर से implement करना बजाय सिर्फ एक बार
Iteratorimplement करके built-in adapter methods reuse करने के।
- किसी custom struct के लिए
Iteratorimplement करने के लिएtype Itemऔरnext()method define करना ज़रूरी है। IntoIteratorimplement करना किसी custom collection type को सीधे एकforloop में उपयोग होने देता है।- एक well-behaved iterator को आखिरकार
next()सेNonereturn करना चाहिए, नहीं तो.collect()जैसे consumers हमेशा के लिए loop करेंगे। - Custom iterators अपने आप iterator adapter methods की पूरी standard library तक access पाते हैं।
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: