pub trait FromIterator<A>: Sized {
// Required method
fn from_iter<T>(iter: T) -> Self
where T: IntoIterator<Item = A>;
}
Expand description
Conversion from an Iterator
.
By implementing FromIterator
for a type, you define how it will be created from an iterator. This is common for types which describe a collection of some kind.
If you want to create a collection from the contents of an iterator, the Iterator::collect()
method is preferred. However, when you need to specify the container type, FromIterator::from_iter()
can be more readable than using a turbofish (e.g. ::<Vec<_>>()
). See the Iterator::collect()
documentation for more examples of its use.
See also: IntoIterator
.
Basic usage:
let five_fives = std::iter::repeat(5).take(5);
let v = Vec::from_iter(five_fives);
assert_eq!(v, vec![5, 5, 5, 5, 5]);
Using Iterator::collect()
to implicitly use FromIterator
:
let five_fives = std::iter::repeat(5).take(5);
let v: Vec<i32> = five_fives.collect();
assert_eq!(v, vec![5, 5, 5, 5, 5]);
Using FromIterator::from_iter()
as a more readable alternative to Iterator::collect()
:
use std::collections::VecDeque;
let first = (0..10).collect::<VecDeque<i32>>();
let second = VecDeque::from_iter(0..10);
assert_eq!(first, second);
Implementing FromIterator
for your type:
#[derive(Debug)]
struct MyCollection(Vec<i32>);
impl MyCollection {
fn new() -> MyCollection {
MyCollection(Vec::new())
}
fn add(&mut self, elem: i32) {
self.0.push(elem);
}
}
impl FromIterator<i32> for MyCollection {
fn from_iter<I: IntoIterator<Item=i32>>(iter: I) -> Self {
let mut c = MyCollection::new();
for i in iter {
c.add(i);
}
c
}
}
let iter = (0..5).into_iter();
let c = MyCollection::from_iter(iter);
assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
let iter = (0..5).into_iter();
let c: MyCollection = iter.collect();
assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
1.0.0 · Source
Creates a value from an iterator.
See the module-level documentation for more.
§Exampleslet five_fives = std::iter::repeat(5).take(5);
let v = Vec::from_iter(five_fives);
assert_eq!(v, vec![5, 5, 5, 5, 5]);
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
1.80.0 · Source§ Source§ 1.0.0 · Source§ Source§ 1.23.0 · Source§Collapses all unit items from an iterator into one.
This is more useful when combined with higher-level abstractions, like collecting to a Result<(), E>
where you only care about errors:
use std::io::*;
let data = vec![1, 2, 3, 4, 5];
let res: Result<()> = data.iter()
.map(|x| writeln!(stdout(), "{x}"))
.collect();
assert!(res.is_ok());
Source§ 1.52.0 · Source§ 1.80.0 · Source§ 1.4.0 · Source§ 1.80.0 · Source§ 1.17.0 · Source§ 1.80.0 · Source§ Source§ 1.0.0 · Source§ Source§ 1.52.0 · Source§ Source§ 1.80.0 · Source§ 1.19.0 · Source§ 1.52.0 · Source§ 1.12.0 · Source§ 1.12.0 · Source§ 1.12.0 · Source§ 1.0.0 · Source§ 1.80.0 · Source§ 1.45.0 · Source§ 1.0.0 · Source§ 1.79.0 · Source§
This implementation turns an iterator of tuples into a tuple of types which implement Default
and Extend
.
This is similar to Iterator::unzip
, but is also composable with other FromIterator
implementations:
let string = "1,2,123,4";
let (numbers, lengths): (Vec<_>, Vec<_>) = string
.split(',')
.map(|s| s.parse().map(|n: u32| (n, s.len())))
.collect::<Result<_, _>>()?;
assert_eq!(numbers, [1, 2, 123, 4]);
assert_eq!(lengths, [1, 1, 3, 1]);
This trait is implemented for tuples up to twelve items long. The impl
s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in 1.85.0.
Collects an iterator into a Vec, commonly called via Iterator::collect()
In general Vec
does not guarantee any particular growth or allocation strategy. That also applies to this trait impl.
Note: This section covers implementation details and is therefore exempt from stability guarantees.
Vec may use any or none of the following strategies, depending on the supplied iterator:
Iterator::size_hint()
pushing
one item at a timeThe last case warrants some attention. It is an optimization that in many cases reduces peak memory consumption and improves cache locality. But when big, short-lived allocations are created, only a small fraction of their items get collected, no further use is made of the spare capacity and the resulting Vec
is moved into a longer-lived structure, then this can lead to the large allocations having their lifetimes unnecessarily extended which can result in increased memory footprint.
In cases where this is an issue, the excess capacity can be discarded with Vec::shrink_to()
, Vec::shrink_to_fit()
or by collecting into Box<[T]>
instead, which additionally reduces the size of the long-lived struct.
static LONG_LIVED: Mutex<Vec<Vec<u16>>> = Mutex::new(Vec::new());
for i in 0..10 {
let big_temporary: Vec<u16> = (0..1024).collect();
let mut result: Vec<_> = big_temporary.into_iter().filter(|i| i % 100 == 0).collect();
result.shrink_to_fit();
LONG_LIVED.lock().unwrap().push(result);
}
1.0.0 · Source§
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4