diff options
Diffstat (limited to '')
-rw-r--r-- | third_party/rust/itertools/src/combinations.rs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/third_party/rust/itertools/src/combinations.rs b/third_party/rust/itertools/src/combinations.rs new file mode 100644 index 0000000000..8759518086 --- /dev/null +++ b/third_party/rust/itertools/src/combinations.rs @@ -0,0 +1,89 @@ +use std::fmt; + +use super::lazy_buffer::LazyBuffer; + +/// An iterator to iterate through all the `k`-length combinations in an iterator. +/// +/// See [`.combinations()`](../trait.Itertools.html#method.combinations) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Combinations<I: Iterator> { + indices: Vec<usize>, + pool: LazyBuffer<I>, + first: bool, +} + +impl<I> Clone for Combinations<I> + where I: Clone + Iterator, + I::Item: Clone, +{ + clone_fields!(indices, pool, first); +} + +impl<I> fmt::Debug for Combinations<I> + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Combinations, indices, pool, first); +} + +/// Create a new `Combinations` from a clonable iterator. +pub fn combinations<I>(iter: I, k: usize) -> Combinations<I> + where I: Iterator +{ + let mut pool: LazyBuffer<I> = LazyBuffer::new(iter); + + for _ in 0..k { + if !pool.get_next() { + break; + } + } + + Combinations { + indices: (0..k).collect(), + pool, + first: true, + } +} + +impl<I> Iterator for Combinations<I> + where I: Iterator, + I::Item: Clone +{ + type Item = Vec<I::Item>; + fn next(&mut self) -> Option<Self::Item> { + if self.first { + if self.pool.is_done() { + return None; + } + self.first = false; + } else if self.indices.len() == 0 { + return None; + } else { + // Scan from the end, looking for an index to increment + let mut i: usize = self.indices.len() - 1; + + // Check if we need to consume more from the iterator + if self.indices[i] == self.pool.len() - 1 { + self.pool.get_next(); // may change pool size + } + + while self.indices[i] == i + self.pool.len() - self.indices.len() { + if i > 0 { + i -= 1; + } else { + // Reached the last combination + return None; + } + } + + // Increment index, and reset the ones to its right + self.indices[i] += 1; + for j in i+1..self.indices.len() { + self.indices[j] = self.indices[j - 1] + 1; + } + } + + // Create result vector based on the indices + Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect()) + } +} |