iter() vs into_iter()
Amit Nadiger
Polyglot(Rust??, Move, C++, C, Kotlin, Java) Blockchain, Polkadot, UTXO, Substrate, Sui, Aptos, Wasm, Proxy-wasm,AndroidTV, Dvb, STB, Linux, Cas, Engineering management.
In Rust, iter() and into_iter() are methods used to create iterators over collections, but they have distinct behaviors:
iter()
fn get_even(input_vec: &Vec<i32>) -> Vec<i32> {
input_vec
.iter()
.filter(|&x| x%2 == 0)
.map(|&x|x*x)
.collect()
}
fn main() {
let numbers = vec![1,2,3,4,5,6,7,8,9];
let mut iter = numbers.iter(); // Iterator of references (&i32)
while let Some(number) = iter.next() {
println!("Number: {}", number); // Accessing through reference
}
// Original collection is still usable
println!("Numbers: {:?}", numbers);
println!("Even numbers {:?}",get_even(&numbers));
println!("Numbers again : {:?}", numbers);
}
/*
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
Number: 6
Number: 7
Number: 8
Number: 9
Numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Even numbers [4, 16, 36, 64]
Numbers again : [1, 2, 3, 4, 5, 6, 7, 8, 9]
*/
into_iter()
fn main() {
let numbers = vec![1,2,3,4,5,6,7,8,9];
let mut iter = numbers.into_iter(); // Iterator of references (&i32)
while let Some(number) = iter.next() {
println!("Number: {}", number); // Accessing through reference
}
// Original collection is still not usable
// uncommenting will cause an error
// println!("Numbers: {:?}", numbers);
}
// Below is the error if we consume the vec which is already called into_iter()
/*
13 | let numbers = vec![1,2,3,4,5,6,7,8,9];
| ------- move occurs because `numbers` has type `Vec<i32>`, which does not implement the `Copy` trait
14 |
15 | let mut iter = numbers.into_iter(); // Iterator of references (&i32)
| ----------- `numbers` moved due to this method call
...
22 | println!("Numbers: {:?}", numbers);
| ^^^^^^^ value borrowed here after move
|
note: `into_iter` takes ownership of the receiver `self`, which moves `numbers`
--> /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/iter/traits/collect.rs:262:18
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: you can `clone` the value and consume it, but this might not be your desired behavior
*/
Sinimarities betwee inetr() and into_iter()
Both iter() and into_iter() provide mechanisms for iterating over collections in Rust, but they differ in terms of ownership and mutability.
Choosing Between iter() and into_iter()
1. Processing elements and discarding the original collection.
2. Transforming elements into a new collection (use collect() on the iterat
Iter() with collect() method :
The collect() method in Rust can be used with iter(), but there's a caveat.
领英推荐
Here's the breakdown:
iter() and Ownership:
collect() and Ownership:
Compatibility:
into_iter() and collect():
Here's an example to illustrate the concept:
fn main() {
let numbers = vec![1,2,3,4,5,6,7,8,9];
// Approach1: Not ideal (less common): collect references
let refs: Vec<&i32> = numbers.iter().collect();
// Needs a collection type that accepts references
// Approach2: More common approach: clone elements and collect
let collected_using_iter: Vec<i32> = numbers.iter().cloned().collect();
// Clone borrowed elements
// Approach3: Collected using map to convert from &i.e referance to value
let collected_using_into_iter: Vec<i32> = numbers.().iter().map(|&x|x).collect()
// Approach4: Ideal scenario for collect
let collected_using_into_iter: Vec<i32> = numbers.into_iter().collect();
// Ownership transferred
}
While collect() can technically be used with iter() under certain conditions, into_iter() is generally the preferred and more efficient choice because it aligns better with ownership semantics and avoids complications with references.
Additional Notes: