itertools
itertools copied to clipboard
Add more set methods: intersect, difference
If you have two sorted iterators (e.g. from BTreeMap::keys) there are various set operations you might want to perform, including union, intersection, difference and symmetric_difference.
union is implemented via itertools::merge.
The others can be implemented with itertools::merge_join_by + filter_map and probably itertools::diff_with. But perhaps there should be more direct implementations?
Here's a direct implementation of intersection, for example:
#[derive(Debug)]
pub struct Intersect<A, B> {
a: A,
b: B,
}
impl<A, B> Iterator for Intersect<A, B>
where
A: Iterator,
B: Iterator<Item = A::Item>,
A::Item: Ord,
{
type Item = A::Item;
fn next(&mut self) -> Option<Self::Item> {
let (mut a, mut b) = (self.a.next(), self.b.next());
loop {
match (a.is_none(), &a).cmp(&(b.is_none(), &b)) {
Ordering::Equal => break a,
Ordering::Less => a = self.a.next(),
Ordering::Greater => b = self.b.next(),
}
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let min = match (self.a.size_hint().1, self.b.size_hint().1) {
(Some(a), Some(b)) => Some(cmp::min(a, b)),
(Some(a), None) | (None, Some(a)) => Some(a),
(None, None) => None,
};
(0, min)
}
}