1use std::collections::HashSet;
2
3pub trait VecExtensions<T> {
4 fn push_unique(&mut self, item: T)
5 where
6 T: PartialEq;
7
8 fn extend_unique(&mut self, iter: impl IntoIterator<Item = T>)
9 where
10 T: PartialEq;
11
12 fn deduplicate(&mut self)
13 where
14 T: std::hash::Hash + Eq + Copy;
15}
16
17impl<T> VecExtensions<T> for Vec<T> {
18 fn push_unique(&mut self, item: T)
19 where
20 T: PartialEq,
21 {
22 if !self.contains(&item) {
23 self.push(item);
24 }
25 }
26
27 fn extend_unique(&mut self, iter: impl IntoIterator<Item = T>)
28 where
29 T: PartialEq,
30 {
31 iter.into_iter().for_each(|i| {
32 self.push_unique(i);
33 });
34 }
35
36 fn deduplicate(&mut self)
37 where
38 T: std::hash::Hash + Eq + Copy,
39 {
40 let mut seen = HashSet::new();
41 self.retain(|t| seen.insert(*t));
42 }
43}
44
45#[cfg(test)]
46mod test {
47 use crate::vec_ext::VecExtensions;
48
49 #[test]
50 fn deduplicate() {
51 let mut vec = vec![0, 1, 2, 2, 1, 0];
52 vec.deduplicate();
53 }
54
55 #[test]
56 fn push_unique() {
57 let mut vec = vec![0, 1, 2];
58 vec.push_unique(2);
59 assert_eq!(vec, vec![0, 1, 2])
60 }
61
62 #[test]
63 fn extend_unique() {
64 let mut vec = vec![0, 1, 2];
65 vec.extend_unique([1, 2, 3]);
66 assert_eq!(vec, vec![0, 1, 2, 3])
67 }
68}