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}