diff options
author | David LeGare <legare@google.com> | 2022-03-04 02:16:57 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-03-04 02:16:57 +0000 |
commit | 3e702301659e7c42649e5c896a1bd9397e0e9b10 (patch) | |
tree | 0ca62eb5d0beeab0cb7ee3c0db8111e81788c2cd /src/unziptuple.rs | |
parent | 6d53fd1c74bf26ad082e430482e1328d63b831ad (diff) | |
parent | 0b915f7185875ec5439b7b4fc0d640dff833a608 (diff) | |
download | itertools-3e702301659e7c42649e5c896a1bd9397e0e9b10.tar.gz |
Update itertools to 0.10.3 am: b72e905c59 am: 49f788bc75 am: 0b915f7185
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/itertools/+/2005035
Change-Id: I668cbaecaf3103c0a394c5576e44163210def870
Diffstat (limited to 'src/unziptuple.rs')
-rw-r--r-- | src/unziptuple.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/unziptuple.rs b/src/unziptuple.rs new file mode 100644 index 0000000..f468f05 --- /dev/null +++ b/src/unziptuple.rs @@ -0,0 +1,80 @@ +/// Converts an iterator of tuples into a tuple of containers. +/// +/// `unzip()` consumes an entire iterator of n-ary tuples, producing `n` collections, one for each +/// column. +/// +/// This function is, in some sense, the opposite of [`multizip`]. +/// +/// ``` +/// use itertools::multiunzip; +/// +/// let inputs = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)]; +/// +/// let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = multiunzip(inputs); +/// +/// assert_eq!(a, vec![1, 4, 7]); +/// assert_eq!(b, vec![2, 5, 8]); +/// assert_eq!(c, vec![3, 6, 9]); +/// ``` +/// +/// [`multizip`]: crate::multizip +pub fn multiunzip<FromI, I>(i: I) -> FromI +where + I: IntoIterator, + I::IntoIter: MultiUnzip<FromI>, +{ + i.into_iter().multiunzip() +} + +/// An iterator that can be unzipped into multiple collections. +/// +/// See [`.multiunzip()`](crate::Itertools::multiunzip) for more information. +pub trait MultiUnzip<FromI>: Iterator { + /// Unzip this iterator into multiple collections. + fn multiunzip(self) -> FromI; +} + +macro_rules! impl_unzip_iter { + ($($T:ident => $FromT:ident),*) => ( + #[allow(non_snake_case)] + impl<IT: Iterator<Item = ($($T,)*)>, $($T, $FromT: Default + Extend<$T>),* > MultiUnzip<($($FromT,)*)> for IT { + fn multiunzip(self) -> ($($FromT,)*) { + // This implementation mirrors the logic of Iterator::unzip as close as possible. + // Unfortunately a lot of the used api there is still unstable represented by + // the commented out parts that follow. + // + // https://doc.rust-lang.org/src/core/iter/traits/iterator.rs.html#2816-2844 + + let mut res = ($($FromT::default(),)*); + let ($($FromT,)*) = &mut res; + + // Still unstable #72631 + // let (lower_bound, _) = self.size_hint(); + // if lower_bound > 0 { + // $($FromT.extend_reserve(lower_bound);)* + // } + + self.fold((), |(), ($($T,)*)| { + // Still unstable #72631 + // $( $FromT.extend_one($T); )* + $( $FromT.extend(std::iter::once($T)); )* + }); + res + } + } + ); +} + +impl_unzip_iter!(); +impl_unzip_iter!(A => FromA); +impl_unzip_iter!(A => FromA, B => FromB); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ, K => FromK); +impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ, K => FromK, L => FromL); |