itertools icon indicating copy to clipboard operation
itertools copied to clipboard

Anything equivalent to Scala's Stream.diff?

Open mandrean opened this issue 6 years ago • 1 comments

I'm trying to find something similar to Scala's Stream.diff:

Computes the multiset difference between this sequence and another sequence.

that: the sequence of elements to remove

returns: a new sequence which contains all elements of this sequence except some of occurrences of elements that also appear in that. If an element value x appears n times in that, then the first n occurrences of x will not form part of the result, but any following occurrences will.

I see there's https://docs.rs/itertools/0.8.1/itertools/fn.diff_with.html, but it doesn't seem to do the same thing? Maybe we call it something else?

mandrean avatar Oct 31 '19 00:10 mandrean

Hmm, I guess you can do:

use itertools::Itertools;
use itertools::EitherOrBoth::{Left, Right, Both};

let a = (0..=10).step_by(2);
let b = (0..=10).step_by(4);
let a_not_b = a
    .merge_join_by(b, |i, j| i.cmp(j))
    .flat_map(|either| {
        match either {
            Left(l) => Some(l),
            _ => None
        }
    })
    .collect::<Vec<i32>>();

assert_eq!(a_not_b, vec![2, 6, 10]);

But it would be nice with a .diff(&self, other: J) or .left_join(&self, other: J) to cut down the boiler plate!

mandrean avatar Oct 31 '19 00:10 mandrean

After #629, you should be able to do this (untested)

let a_not_b = a
    .merge_join_by(b, |i, j| i.cmp(j))
    .filter_map(EitherOrBoth::just_left)
    .collect_vec();

It cuts down much of the boilerplate so I think it's good enough.

Philippe-Cholet avatar Feb 07 '24 09:02 Philippe-Cholet