-
Notifications
You must be signed in to change notification settings - Fork 14k
Add Iterator::collect_into and Iterator::collect_with #92982
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1741,6 +1741,154 @@ pub trait Iterator { | |
| FromIterator::from_iter(self) | ||
| } | ||
|
|
||
| /// 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. | ||
| /// | ||
| /// The collection is passed and returned by mutable reference. | ||
| /// To pass it by by value, use [`collect_with`]. | ||
| /// | ||
| /// [`collect_with`]: Iterator::collect_with | ||
| /// | ||
| /// 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_more_collects)] | ||
| /// | ||
| /// let a = [1, 2, 3]; | ||
| /// let mut vec: Vec::<i32> = Vec::new(); | ||
| /// | ||
| /// a.iter().map(|&x| x * 2).collect_into(&mut vec); | ||
| /// a.iter().map(|&x| x * 10).collect_into(&mut vec); | ||
| /// | ||
| /// assert_eq!(vec![2, 4, 6, 10, 20, 30], vec); | ||
| /// ``` | ||
| /// | ||
| /// `Vec` can have a manual set capacity to avoid reallocating it: | ||
| /// | ||
| /// ``` | ||
| /// #![feature(iter_more_collects)] | ||
| /// | ||
| /// 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()); | ||
| /// ``` | ||
| /// | ||
| /// The returned mutable reference can be used to continue the call chain: | ||
| /// | ||
| /// ``` | ||
| /// #![feature(iter_more_collects)] | ||
| /// | ||
| /// let a = [1, 2, 3]; | ||
| /// let mut vec: Vec::<i32> = Vec::new(); | ||
| /// | ||
| /// 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); | ||
| /// ``` | ||
| // must_use not added here since collect_into takes a (mutable) reference | ||
| #[inline] | ||
| #[unstable(feature = "iter_more_collects", reason = "new API", issue = "none")] | ||
| fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E | ||
| where | ||
| Self: Sized, | ||
| { | ||
| collection.extend(self); | ||
| collection | ||
| } | ||
|
|
||
| /// Collects all the items from an iterator with 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. | ||
| /// | ||
| /// The collection is passed and returned by value. To pass it by by mutable | ||
| /// reference, use [`collect_into`]. | ||
| /// | ||
| /// [`collect_into`]: Iterator::collect_into | ||
| /// | ||
| /// This is useful when you want to pre-allocate memory for the collection | ||
| /// that will contains the iterator items. | ||
| /// | ||
| /// 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_more_collects)] | ||
| /// | ||
| /// let a = [1, 2, 3]; | ||
| /// | ||
| /// let doubled = a.iter() | ||
| /// .map(|&x| x * 2) | ||
| /// .collect_with(Vec::new()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this sets a bad example since it uses Which is a silly thing to do when you can just use For that reason I think the name also is suboptimal since it associates itself with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I put Vec::with_capacity(3) instead?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, so if I understood correctly, I should use a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This lack of optimisation for the empty case is a bit of a worry in terms of whether
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree that it is almost never a good idea. I also like more the turbofish syntax where applicable. My idea for let len1 = vec![1, 2, 3]
.into_iter()
.filter(|&x| x < 3)
.collect_with(Vec::with_capacity(2))
.len();
// Instead of
let mut vec = Vec::with_capacity(2);
let len2 = vec![1, 2, 3]
.into_iter()
.filter(|&x| x < 3)
.collect_into(&mut vec)
.len();I think we could specify it in the doc. However, someone could still misuse the method. Calling Eventually, I realised |
||
| /// | ||
| /// assert_eq!(vec![2, 4, 6], doubled); | ||
| /// ``` | ||
| /// | ||
| /// Collecting an iterator into a `Vec` with manually set capacity in order | ||
| /// to avoid reallocating it: | ||
| /// | ||
| /// ``` | ||
| /// #![feature(iter_more_collects)] | ||
| /// | ||
| /// let doubled = (0..50).map(|x| x * 2) | ||
| /// .collect_with(Vec::with_capacity(50)); | ||
| /// | ||
| /// assert_eq!(50, doubled.capacity()); | ||
| /// ``` | ||
| /// | ||
| /// Passing to `collect_into` a collection with less capacity than necessary | ||
| /// can lead to less performant code: | ||
| /// | ||
| /// ``` | ||
| /// #![feature(iter_more_collects)] | ||
| /// | ||
| /// let chars = ['g', 'd', 'k', 'k', 'n']; | ||
| /// | ||
| /// let hello = chars.iter() | ||
| /// .map(|&x| x as u8) | ||
| /// .map(|x| (x + 1) as char) | ||
| /// .collect_with(String::with_capacity(2)); | ||
| /// | ||
| /// assert_eq!("hello", hello); | ||
| /// assert!(5 <= hello.capacity()); // At least one reallocation happened | ||
| /// ``` | ||
| #[inline] | ||
| #[unstable(feature = "iter_more_collects", reason = "new API", issue = "none")] | ||
| #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] | ||
| fn collect_with<E: Extend<Self::Item>>(self, mut collection: E) -> 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`. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.