pencil_box/array/
intersection.rs

1use std::collections::{HashMap, HashSet};
2use std::hash::Hash;
3
4/// Computes the intersection of multiple collections, returning only elements common to **all** inputs.
5///
6/// # Type Parameters
7///
8/// - `T`: The element type. Must implement `Clone`, `Eq`, and `Hash`.
9/// - `U`: A slice-like container that implements `AsRef<[T]>`.
10///
11/// # Arguments
12///
13/// - `values`: A slice of collections (`&[U]`) to be intersected, where each `U` can be converted into a slice of `T`.
14///
15/// # Returns
16///
17/// A `Vec<T>` containing only those elements that appear in **every** input collection.
18/// The result does **not** preserve the original order and contains **no duplicates**.
19///
20/// # Supported Input Types
21///
22/// Any slice-like container that implements `AsRef<[T]>`, including:
23///
24/// - `&[&[T]]`
25/// - `&[Vec<T>]`
26/// - `&[Box<[T]>]`
27/// - `&Vec<Vec<T>>`
28/// - `Vec<&[T]>`
29/// - `Vec<&Vec<T>>`
30/// - `Vec<Vec<T>>`
31/// - `Vec<Box<[T]>>`
32/// - `&[[T; N]]` and `&[T; N]`
33///
34/// # Behavior
35///
36/// - Each collection is scanned for distinct elements.
37/// - Elements are counted only once per collection (i.e., duplicates within a single collection are ignored).
38/// - Only elements that appear in **all** collections are returned.
39/// - If `values` is empty, returns an empty vector.
40/// - If any single input collection is empty, the result is also empty.
41/// - The output contains no duplicates.
42///
43/// # Performance
44///
45/// - **Time Complexity**: O(n × m), where `n` is the number of input collections and `m` is the average length of each collection.
46/// - **Space Complexity**: O(u), where `u` is the number of unique elements across all collections.
47///
48/// # Panic Safety
49///
50/// This function is 100% panic-free on valid input.
51///
52/// # Examples
53///
54/// 🧪 `&[&[T]]`
55/// ```
56/// use pencil_box::array::intersection::intersection;
57/// let a = &[1, 2, 3][..];
58/// let b = &[2, 3, 4][..];
59/// let c = &[2, 3, 5][..];
60/// let result = intersection(&[a, b, c]);
61/// assert_eq!(result, vec![2, 3]);
62/// ```
63///
64/// 🧪 `&[Vec<T>]`
65/// ```
66/// let a = vec![1, 2, 3];
67/// let b = vec![2, 3, 4];
68/// let c = vec![2, 3, 5];
69/// let result = intersection(&[a, b, c]);
70/// assert_eq!(result, vec![2, 3]);
71/// ```
72///
73/// 🧪 `&[Box<[T]>]`
74/// ```
75/// let a: Box<[i32]> = Box::new([1, 2, 3]);
76/// let b: Box<[i32]> = Box::new([2, 3, 4]);
77/// let c: Box<[i32]> = Box::new([2, 3, 5]);
78/// let result = intersection(&[a, b, c]);
79/// assert_eq!(result, vec![2, 3]);
80/// ```
81///
82/// 🧪 `&Vec<Vec<T>>`
83/// ```
84/// let input = vec![
85///     vec![1, 2, 3],
86///     vec![2, 3, 4],
87///     vec![2, 3, 5],
88/// ];
89/// let result = intersection(&input);
90/// assert_eq!(result, vec![2, 3]);
91/// ```
92///
93/// 🧪 `Vec<&[T]>`
94/// ```
95/// let a = &[1, 2, 3][..];
96/// let b = &[2, 3, 4][..];
97/// let c = &[2, 3, 5][..];
98/// let input: Vec<&[i32]> = vec![a, b, c];
99/// let result = intersection(&input);
100/// assert_eq!(result, vec![2, 3]);
101/// ```
102///
103/// 🧪 `Vec<&Vec<T>>`
104/// ```
105/// let a = vec![1, 2, 3];
106/// let b = vec![2, 3, 4];
107/// let c = vec![2, 3, 5];
108/// let input: Vec<&Vec<i32>> = vec![&a, &b, &c];
109/// let result = intersection(&input);
110/// assert_eq!(result, vec![2, 3]);
111/// ```
112///
113/// 🧪 `Vec<Vec<T>>`
114/// ```
115/// let input = vec![
116///     vec![1, 2, 3],
117///     vec![2, 3, 4],
118///     vec![2, 3, 5],
119/// ];
120/// let result = intersection(&input);
121/// assert_eq!(result, vec![2, 3]);
122/// ```
123///
124/// 🧪 `Vec<Box<[T]>>`
125/// ```
126/// let a: Box<[i32]> = Box::new([1, 2, 3]);
127/// let b: Box<[i32]> = Box::new([2, 3, 4]);
128/// let c: Box<[i32]> = Box::new([2, 3, 5]);
129/// let input = vec![a, b, c];
130/// let result = intersection(&input);
131/// assert_eq!(result, vec![2, 3]);
132/// ```
133///
134/// 🧪 `&[[T; N]]`
135/// ```
136/// let a: [i32; 3] = [1, 2, 3];
137/// let b: [i32; 3] = [2, 3, 4];
138/// let c: [i32; 3] = [2, 3, 5];
139/// let input: &[[i32; 3]] = &[a, b, c];
140/// let result = intersection(input);
141/// assert_eq!(result, vec![2, 3]);
142/// ```
143///
144/// 🧪 `&[T; N]`
145/// ```
146/// let a: [i32; 3] = [1, 2, 3];
147/// let b: [i32; 3] = [2, 3, 4];
148/// let c: [i32; 3] = [2, 3, 5];
149/// let input = [&a[..], &b[..], &c[..]];
150/// let result = intersection(&input);
151/// assert_eq!(result, vec![2, 3]);
152/// ```
153///
154/// 🧪 `String` (owned)
155/// ```
156/// let a = vec!["a".to_string(), "b".to_string()];
157/// let b = vec!["b".to_string(), "c".to_string()];
158/// let c = vec!["b".to_string(), "d".to_string()];
159/// let result = intersection(&[a, b, c]);
160/// assert_eq!(result, vec!["b"]);
161/// ```
162///
163/// 🧪 `&str` (references)
164/// ```
165/// let a = ["a", "b"];
166/// let b = ["b", "c"];
167/// let c = ["b", "d"];
168/// let result = intersection(&[&a[..], &b[..], &c[..]]);
169/// assert_eq!(result, vec!["b"]);
170/// ```
171///
172/// 🧪 Structs (owned)
173/// ```
174/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
175/// struct Item { id: u8 }
176///
177/// let a = vec![Item { id: 1 }, Item { id: 2 }];
178/// let b = vec![Item { id: 2 }, Item { id: 3 }];
179/// let c = vec![Item { id: 2 }, Item { id: 4 }];
180/// let result = intersection(&[a, b, c]);
181/// assert_eq!(result, vec![Item { id: 2 }]);
182/// ```
183///
184/// 🧪 Structs (references)
185/// ```
186/// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
187/// struct Item { id: u8 }
188///
189/// let a = [Item { id: 1 }, Item { id: 2 }];
190/// let b = [Item { id: 2 }, Item { id: 3 }];
191/// let c = [Item { id: 2 }, Item { id: 4 }];
192///
193/// let va: Vec<&Item> = a.iter().collect();
194/// let vb: Vec<&Item> = b.iter().collect();
195/// let vc: Vec<&Item> = c.iter().collect();
196/// let result = intersection(&[va, vb, vc]);
197/// assert_eq!(result.len(), 1);
198/// assert_eq!(result[0].id, 2);
199/// ```
200
201pub fn intersection<T, U>(values: &[U]) -> Vec<T>
202where
203    U: AsRef<[T]>,
204    T: Clone + Eq + Hash,
205{
206    let mut count: HashMap<T, usize> = HashMap::new();
207    for sub_array in values {
208        let mut seen = HashSet::new();
209        for item in sub_array.as_ref().iter() {
210            if seen.insert(item) {
211                count
212                    .entry(item.clone())
213                    .and_modify(|v| *v += 1)
214                    .or_insert(1);
215            }
216        }
217    }
218    count
219        .into_iter()
220        .filter_map(|(key, value)| {
221            if value == values.len() {
222                Some(key.clone())
223            } else {
224                None
225            }
226        })
227        .collect()
228}