Skip to content

Commit

Permalink
Rollup merge of #93057 - frengor:iter_collect_into, r=m-ou-se
Browse files Browse the repository at this point in the history
Add Iterator::collect_into

This PR adds `Iterator::collect_into` as proposed by ``@cormacrelf`` in #48597 (see #48597 (comment)).
Followup of #92982.

This adds the following method to the Iterator trait:

```rust
fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E
```
  • Loading branch information
matthiaskrgr authored Mar 9, 2022
2 parents 2567d0f + 63eddb3 commit d5c05fc
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 0 deletions.
71 changes: 71 additions & 0 deletions library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1859,6 +1859,77 @@ pub trait Iterator {
try_process(self, |i| i.collect())
}

/// Collects all the items from an iterator into a collection.
///
/// This method consumes the iterator and adds all its items to the
/// passed collection. The collection is then returned, so the call chain
/// can be continued.
///
/// This is useful when you already have a collection and wants to add
/// the iterator items to it.
///
/// This method is a convenience method to call [Extend::extend](trait.Extend.html),
/// but instead of being called on a collection, it's called on an iterator.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(iter_collect_into)]
///
/// let a = [1, 2, 3];
/// let mut vec: Vec::<i32> = vec![0, 1];
///
/// a.iter().map(|&x| x * 2).collect_into(&mut vec);
/// a.iter().map(|&x| x * 10).collect_into(&mut vec);
///
/// assert_eq!(vec![0, 1, 2, 4, 6, 10, 20, 30], vec);
/// ```
///
/// `Vec` can have a manual set capacity to avoid reallocating it:
///
/// ```
/// #![feature(iter_collect_into)]
///
/// let a = [1, 2, 3];
/// let mut vec: Vec::<i32> = Vec::with_capacity(6);
///
/// a.iter().map(|&x| x * 2).collect_into(&mut vec);
/// a.iter().map(|&x| x * 10).collect_into(&mut vec);
///
/// assert_eq!(6, vec.capacity());
/// println!("{:?}", vec);
/// ```
///
/// The returned mutable reference can be used to continue the call chain:
///
/// ```
/// #![feature(iter_collect_into)]
///
/// let a = [1, 2, 3];
/// let mut vec: Vec::<i32> = Vec::with_capacity(6);
///
/// let count = a.iter().collect_into(&mut vec).iter().count();
///
/// assert_eq!(count, vec.len());
/// println!("Vec len is {}", count);
///
/// let count = a.iter().collect_into(&mut vec).iter().count();
///
/// assert_eq!(count, vec.len());
/// println!("Vec len now is {}", count);
/// ```
#[inline]
#[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")]
fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E
where
Self: Sized,
{
collection.extend(self);
collection
}

/// Consumes an iterator, creating two collections from it.
///
/// The predicate passed to `partition()` can return `true`, or `false`.
Expand Down
8 changes: 8 additions & 0 deletions library/core/tests/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,14 @@ fn test_try_collect() {
assert_eq!(v, Continue(vec![4, 5]));
}

#[test]
fn test_collect_into() {
let a = vec![1, 2, 3, 4, 5];
let mut b = Vec::new();
a.iter().cloned().collect_into(&mut b);
assert!(a == b);
}

// just tests by whether or not this compiles
fn _empty_impl_all_auto_traits<T>() {
use std::panic::{RefUnwindSafe, UnwindSafe};
Expand Down
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#![feature(slice_partition_dedup)]
#![feature(int_log)]
#![feature(iter_advance_by)]
#![feature(iter_collect_into)]
#![feature(iter_partition_in_place)]
#![feature(iter_intersperse)]
#![feature(iter_is_partitioned)]
Expand Down

0 comments on commit d5c05fc

Please sign in to comment.