use std::borrow::Borrow; use std::collections::hash_set::Iter; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; use crate::fxhash::FxHashSet; use crate::{debug_fmt_iter, fmt_iter}; #[macro_export] macro_rules! set { () => { $crate::set::Set::new() }; ($($x: expr),+ $(,)?) => {{ let mut set = $crate::set::Set::new(); $(set.insert($x);)+ set }}; } #[derive(Clone)] pub struct Set { elems: FxHashSet, } // Use `fast_eq` for faster comparisons impl PartialEq for Set { fn eq(&self, other: &Set) -> bool { if self.len() != other.len() { return false; } self.iter() .all(|l_key| other.iter().any(|r_key| l_key == r_key)) } } impl Eq for Set {} impl Default for Set { fn default() -> Self { Self::new() } } impl Hash for Set { fn hash(&self, state: &mut H) { self.elems.iter().collect::>().hash(state); } } impl From> for Set { fn from(vec: Vec) -> Self { vec.into_iter().collect() } } impl From<[T; N]> for Set { fn from(arr: [T; N]) -> Self { arr.into_iter().collect() } } impl fmt::Debug for Set { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{{{}}}", debug_fmt_iter(self.elems.iter())) } } impl fmt::Display for Set { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{{{}}}", fmt_iter(self.elems.iter())) } } impl FromIterator for Set { #[inline] fn from_iter>(iter: I) -> Set { let mut set = Set::new(); set.extend(iter); set } } impl Set { #[inline] pub fn new() -> Self { Self { elems: FxHashSet::default(), } } } impl Set { pub fn with_capacity(capacity: usize) -> Self { Self { elems: FxHashSet::with_capacity_and_hasher(capacity, Default::default()), } } #[inline] pub fn len(&self) -> usize { self.elems.len() } #[inline] pub fn is_empty(&self) -> bool { self.elems.is_empty() } #[inline] pub fn iter(&self) -> Iter<'_, T> { self.elems.iter() } } impl IntoIterator for Set { type Item = T; type IntoIter = as IntoIterator>::IntoIter; #[inline] fn into_iter(self) -> Self::IntoIter { self.elems.into_iter() } } impl Set { #[inline] pub fn get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: ?Sized + Hash + Eq, { self.elems.get(value) } pub fn get_by(&self, value: &Q, cmp: impl Fn(&Q, &Q) -> bool) -> Option<&T> where T: Borrow, Q: ?Sized + Hash + Eq, { self.elems.iter().find(|&v| cmp(v.borrow(), value)) } #[inline] pub fn fast_eq(&self, other: &Set) -> bool { self.elems == other.elems } #[inline] pub fn contains(&self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Hash + Eq, { self.elems.contains(value) } #[inline] pub fn insert(&mut self, value: T) -> bool { self.elems.insert(value) } #[inline] pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Hash + Eq, { self.elems.remove(value) } #[inline] pub fn extend>(&mut self, iter: I) { self.elems.extend(iter); } pub fn extended>(mut self, iter: I) -> Self { self.elems.extend(iter); self } #[inline] pub fn is_superset(&self, other: &Set) -> bool { self.elems.is_superset(&other.elems) } #[inline] pub fn merge(&mut self, other: Self) { self.elems.extend(other.elems); } #[inline] pub fn concat(mut self, other: Self) -> Self { self.elems.extend(other.elems); self } /// remove all elements for which the predicate returns false #[inline] pub fn retain(&mut self, f: impl FnMut(&T) -> bool) { self.elems.retain(f); } } impl Set { /// ``` /// # use erg_common::set; /// assert_eq!(set!{1, 2, 3}.union(&set!{2, 3, 4}), set!{1, 2, 3, 4}); /// ``` #[inline] pub fn union(&self, other: &Set) -> Set { let u = self.elems.union(&other.elems); Self { elems: u.into_iter().cloned().collect(), } } pub fn union_iter<'a>(&'a self, other: &'a Set) -> impl Iterator { self.elems.union(&other.elems) } pub fn union_from_iter>(&self, iter: I) -> Set { self.union(&iter.collect()) } /// ``` /// # use erg_common::set; /// assert_eq!(set!{1, 2, 3}.intersection(&set!{2, 3, 4}), set!{2, 3}); /// ``` #[inline] pub fn intersection(&self, other: &Set) -> Set { let u = self.elems.intersection(&other.elems); Self { elems: u.into_iter().cloned().collect(), } } pub fn intersec_iter<'a>(&'a self, other: &'a Set) -> impl Iterator { self.elems.intersection(&other.elems) } pub fn intersec_from_iter>(&self, iter: I) -> Set { self.intersection(&iter.collect()) } /// ``` /// # use erg_common::set; /// # use erg_common::set::Set; /// assert_eq!(Set::multi_intersection([set!{1, 3}, set!{1, 2}].into_iter()), set!{1}); /// assert_eq!(Set::multi_intersection([set!{1, 3}, set!{1, 2}, set!{2}].into_iter()), set!{1, 2}); /// assert_eq!(Set::multi_intersection([set!{1, 3}, set!{1, 2}, set!{2, 3}].into_iter()), set!{1, 2, 3}); /// ``` pub fn multi_intersection(mut i: I) -> Set where I: Iterator> + Clone, { let mut res = set! {}; while let Some(s) = i.next() { res = res.union_from_iter( s.into_iter() .filter(|x| i.clone().any(|set| set.contains(x))), ); } res } pub fn difference(&self, other: &Set) -> Set { let u = self.elems.difference(&other.elems); Self { elems: u.into_iter().cloned().collect(), } } pub fn diff_iter<'a>(&'a self, other: &'a Set) -> impl Iterator { self.elems.difference(&other.elems) } } impl Set { pub fn max(&self) -> Option<&T> { self.iter().max_by(|x, y| x.cmp(y)) } pub fn min(&self) -> Option<&T> { self.iter().min_by(|x, y| x.cmp(y)) } } impl Set { pub fn folded_display(&self) -> String { self.iter() .fold("".to_string(), |acc, x| acc + &x.to_string() + "\n") } }