-
Notifications
You must be signed in to change notification settings - Fork 355
Add array_chunks #1023
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
base: master
Are you sure you want to change the base?
Add array_chunks #1023
Changes from all commits
29080b4
37a77b8
e3af5fb
3aa4f60
add6f83
d3db791
e1d5072
eb82706
1efe4a8
00b8c1e
6a2f832
a71605b
41a68ac
66243aa
bec8ee3
e923eb1
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 |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| use crate::Itertools; | ||
|
|
||
| macro_rules! const_assert_positive { | ||
| ($N: ty) => { | ||
| trait StaticAssert<const N: usize> { | ||
| const ASSERT: bool; | ||
| } | ||
|
|
||
| impl<const N: usize> StaticAssert<N> for () { | ||
| const ASSERT: bool = { | ||
| assert!(N > 0); | ||
| true | ||
| }; | ||
| } | ||
|
|
||
| assert!(<() as StaticAssert<N>>::ASSERT); | ||
| }; | ||
| } | ||
|
|
||
| /// An iterator that groups the items in arrays of const generic size `N`. | ||
| /// | ||
| /// See [`.next_array()`](crate::Itertools::next_array) for details. | ||
| #[derive(Debug, Clone)] | ||
| pub struct Arrays<I: Iterator, const N: usize> { | ||
| iter: I, | ||
| } | ||
|
|
||
| impl<I: Iterator, const N: usize> Arrays<I, N> { | ||
| pub(crate) fn new(iter: I) -> Self { | ||
| const_assert_positive!(N); | ||
|
|
||
| // TODO should we use iter.fuse() instead? | ||
| Self { iter } | ||
| } | ||
| } | ||
|
|
||
| impl<I: Iterator, const N: usize> Iterator for Arrays<I, N> { | ||
| type Item = [I::Item; N]; | ||
|
|
||
| fn next(&mut self) -> Option<Self::Item> { | ||
| self.iter.next_array() | ||
| } | ||
|
|
||
| fn size_hint(&self) -> (usize, Option<usize>) { | ||
| // also verified in `new()` | ||
| const_assert_positive!(N); | ||
| let (lo, hi) = self.iter.size_hint(); | ||
|
ronnodas marked this conversation as resolved.
|
||
| (lo / N, hi.map(|hi| hi / N)) | ||
| } | ||
| } | ||
|
|
||
| impl<I: ExactSizeIterator, const N: usize> ExactSizeIterator for Arrays<I, N> {} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -101,6 +101,7 @@ pub mod structs { | |
| }; | ||
| pub use crate::all_equal_value_err::AllEqualValueError; | ||
| pub use crate::array_impl::{ArrayWindows, CircularArrayWindows}; | ||
| pub use crate::arrays::Arrays; | ||
| #[cfg(feature = "use_alloc")] | ||
| pub use crate::combinations::{ArrayCombinations, Combinations}; | ||
| #[cfg(feature = "use_alloc")] | ||
|
|
@@ -179,6 +180,7 @@ pub use crate::with_position::Position; | |
| pub use crate::ziptuple::multizip; | ||
| mod adaptors; | ||
| mod array_impl; | ||
| mod arrays; | ||
| mod either_or_both; | ||
| pub use crate::either_or_both::EitherOrBoth; | ||
| #[doc(hidden)] | ||
|
|
@@ -790,6 +792,45 @@ pub trait Itertools: Iterator { | |
| groupbylazy::new_chunks(self, size) | ||
| } | ||
|
|
||
| /// Return an iterator that groups the items in arrays of const generic size `N`. | ||
| /// | ||
| /// `N == 0` is a compile-time (but post-monomorphization) error. | ||
|
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. Is it really important for users that it is post-monomorphization?
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. It won't be caught by |
||
| /// | ||
| /// See also the method [`.next_array()`](Itertools::next_array). | ||
| /// | ||
| /// ```rust | ||
| /// use itertools::Itertools; | ||
| /// let mut v = Vec::new(); | ||
| /// for [a, b] in (1..5).arrays() { | ||
| /// v.push([a, b]); | ||
| /// } | ||
| /// assert_eq!(v, vec![[1, 2], [3, 4]]); | ||
| /// | ||
| /// // this requires a type hint | ||
| /// let it = (1..7).arrays::<3>(); | ||
| /// itertools::assert_equal(it, vec![[1, 2, 3], [4, 5, 6]]); | ||
| /// | ||
| /// // you can also specify the complete type | ||
|
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. Let's not encourage people to spell iterator types
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. Note that such an example is included in the docs for
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. As you wish. |
||
| /// use itertools::Arrays; | ||
| /// use std::ops::Range; | ||
| /// | ||
| /// let it: Arrays<Range<u32>, 3> = (1..7).arrays(); | ||
| /// itertools::assert_equal(it, vec![[1, 2, 3], [4, 5, 6]]); | ||
| /// ``` | ||
| /// | ||
| /// ```compile_fail | ||
| /// use itertools::Itertools; | ||
| /// | ||
| /// let mut it = (1..5).arrays::<0>(); | ||
| /// assert_eq!(Some([]), it.next()); | ||
| /// ``` | ||
| fn arrays<const N: usize>(self) -> Arrays<Self, N> | ||
|
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. IMO
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. To add context, I was trying to avoid triggering the |
||
| where | ||
| Self: Sized, | ||
| { | ||
| Arrays::new(self) | ||
| } | ||
|
|
||
| /// Return an iterator over all contiguous windows producing tuples of | ||
| /// a specific size (up to 12). | ||
| /// | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It strikes me as a code smell that
Ndoesn't appear in the definition here. Shouldn'tpartialbe anArrayBuilder<T, N>?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making it
ArrayBuilder<T, N>a priori makes sense, but I had trouble with the bounds for theimpl Clonein that case. Note thatMaybeUninit<T>: ClonerequiresT: Copy.Maybe it could also be
array::IntoIter<T, N>or a hypotheticalArrayBuilder::IntoIter<T, N>(this is close to what the unstableIterator::ArrayChunksdoes) but I think the unsafe code for that would need to be more careful.The state you need to keep track of doesn't really depend on
N(exceptpartial.len() <= Nbut this is sort of incidental). HoweverArraysneeds to haveNas a parameter forArrays::Itemto be well-defined.Suggestions?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, should be ArrayBuilder, because this brings it closer to no_alloc.
Maybe this array builder could also be re-used in
next.Can you remember/share the exact problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@phimuemue If it holds an
ArrayBuilder<T>then it won't beClonewithoutT : Copy. But we should haveArrays<I, N>: ClonewhenI: CloneandI::Item : Clone.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Then, let's implement it without partial/remaining for now.
(Because if we extend our ArrayBuilder further and further, we land at (a less tested version of) ArrayVec.)