How to iterate over and filter an array?
In cases like this, it's very useful to force the compiler to tell you the type of the variable. Let's trigger a type error by assigning the closure argument to an incompatible type:
array_iter.filter(|x| { let _: () = x; x == 2 });
This fails with:
error[E0308]: mismatched types
--> src/lib.rs:4:41
|
4 | array_iter.filter(|x| { let _: () = x; x == 2 });
| -- ^ expected `()`, found `&&{integer}`
| |
| expected due to this
Now we know the type of x
is a &&{integer}
- a reference to a reference to some kind of integer. We can then match against that instead:
fn hooray() {
let array = [1, 4, 3, 2, 2];
let array_iter = array.into_iter();
array_iter.filter(|&&x| x == 2);
}
The question now becomes "why is it a reference to a reference"? The short version is that the iterator of an array returns references (see the type Item = &'a T
part). In addition, Iterator::filter
passes a reference to the closure to prevent moving and subsequently losing non-Copy
types.
In Rust 1.51, you can use array::IntoIter
to get a by-value iterator:
fn hooray() {
let array = [1, 4, 3, 2, 2];
let array_iter = std::array::IntoIter::new(array);
array_iter.filter(|&x| x == 2);
}
Arrays are the type [T; N]
in Rust, for any element type T
and a constant number N
. It's a fixed size array.
Rust doesn't implement IntoIterator
for arrays at the moment. All arrays coerce to slices (type [T]
) and the slice methods are available on the array because of this. The arrays also get the slice's iterator, which is called std::slice::Iter<'a, T>
and has elements of type &'a T
: it iterates by reference!
This is why into_iter()
on a Range<i32>
produces an iterator of i32
and into_iter()
on a [i32; 5]
produces an iterator of &i32
.
If you need by value iterators for arrays and
-
You are using Rust 1.51 or newer, you can use
array::IntoIter
:fn does_now_compile() { let array = [1, 4, 3, 2, 2]; let array_iter = std::array::IntoIter::new(array); array_iter.filter(|&x| x == 2); }
-
You are using older versions of Rust, by-value iterators have been implemented in the broader ecosystem, see arrayvec and literator.