rodash/
difference_all.rs

1use crate::difference;
2
3/// Creates a vector of `array` values not included in the `others` nested arrays.
4///
5/// * `array` - The array to inspect.
6/// * `others` - The nested values to exclude.
7/// * `is_sorted` - The sorted flag. Should be set to `Some(true)` if you are certain that `other`
8///   is a sorted array. Internally, binary search is utilized when this flag is provided and is
9///   truthy, enabling searching in `O(log n)` time, compared to the `O(n)` time complexity of
10///   linear search otherwise.
11///
12/// # Examples
13///
14/// ```
15/// use rodash::difference_all;
16///
17/// let result = difference_all(&[2, 1, 2, 3], vec![&[3, 4], &[3, 2]], None);
18/// assert_eq!(result, [1]);
19/// ```
20pub fn difference_all<A>(array: &[A], others: Vec<&[A]>, is_sorted: Option<bool>) -> Vec<A>
21where
22    A: PartialEq + Ord + Clone,
23{
24    let flattened = others
25        .into_iter()
26        .flatten()
27        .map(|item| item.to_owned())
28        .collect::<Vec<_>>();
29
30    difference(array, &flattened, is_sorted)
31}
32
33/// A trait that implements the [DifferenceAll::difference_all] method on arrays.
34pub trait DifferenceAll<A, I>
35where
36    A: IntoIterator,
37    I: PartialEq + Ord + Clone,
38{
39    /// Creates a vector of values in this array that are not included in the `others` nested
40    /// arrays.
41    ///
42    /// * `others` - The nested values to exclude.
43    /// * `is_sorted` - The sorted flag. Should be set to `Some(true)` if you are certain that
44    ///   `other` is a sorted array. Internally, binary search is utilized when this flag is
45    ///   provided and is truthy, enabling searching in `O(log n)` time, compared to the `O(n)` time
46    ///   complexity of linear search otherwise.
47    ///
48    /// # Examples
49    ///
50    /// ```
51    /// use rodash::DifferenceAll;
52    ///
53    /// assert_eq!(
54    ///     [2, 1, 2, 3].difference_all(vec![&[3, 4], &[3, 2]], None),
55    ///     [1]
56    /// );
57    /// ```
58    fn difference_all(&self, others: Vec<&[I]>, is_sorted: Option<bool>) -> Vec<I>;
59}
60
61impl<A> DifferenceAll<Vec<A>, A> for Vec<A>
62where
63    A: PartialEq + Ord + Clone,
64{
65    fn difference_all(&self, others: Vec<&[A]>, is_sorted: Option<bool>) -> Vec<A> {
66        difference_all(self, others, is_sorted)
67    }
68}
69
70impl<A, const N: usize> DifferenceAll<[A; N], A> for [A; N]
71where
72    A: PartialEq + Ord + Clone,
73{
74    fn difference_all(&self, others: Vec<&[A]>, is_sorted: Option<bool>) -> Vec<A> {
75        difference_all(self, others, is_sorted)
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn can_return_difference_of_multiple_arrays() {
85        let result = difference_all(&[2, 1, 2, 3], vec![&[3, 4], &[3, 2]], None);
86        assert_eq!(result, [1]);
87
88        assert_eq!(
89            vec![2, 1, 2, 3].difference_all(vec![&[3, 4], &[3, 2]], None),
90            [1]
91        );
92
93        assert_eq!(
94            [2, 1, 2, 3].difference_all(vec![&[3, 4], &[3, 2]], None),
95            [1]
96        );
97    }
98
99    #[test]
100    fn can_return_difference_of_multiple_sorted_arrays() {
101        let result = difference_all(&[2, 1, 2, 3], vec![&[3, 4, 5], &[2, 3, 4]], Some(true));
102        assert_eq!(result, [1]);
103
104        assert_eq!(
105            vec![2, 1, 2, 3].difference_all(vec![&[3, 4, 5], &[2, 3, 4]], Some(true)),
106            [1]
107        );
108
109        assert_eq!(
110            [2, 1, 2, 3].difference_all(vec![&[3, 4, 5], &[2, 3, 4]], Some(true)),
111            [1]
112        );
113    }
114}