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::traits::Immutable; use crate::{debug_fmt_iter, fmt_iter, get_hash}; #[cfg(feature = "pylib")] use pyo3::prelude::PyAnyMethods; #[cfg(feature = "pylib")] use pyo3::{FromPyObject, IntoPy, PyAny, PyObject, Python}; #[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, } #[cfg(feature = "pylib")] impl> IntoPy for Set { fn into_py(self, py: Python<'_>) -> PyObject { self.elems.into_py(py) } } #[cfg(feature = "pylib")] impl<'source, T> FromPyObject<'source> for Set where T: Hash + Eq + FromPyObject<'source>, { fn extract_bound(ob: &pyo3::Bound<'source, PyAny>) -> pyo3::PyResult { Ok(Set { elems: ob.extract::>()?, }) } } impl PartialEq for Set { fn eq(&self, other: &Set) -> bool { self.elems.eq(&other.elems) } } impl Eq for Set {} impl Default for Set { fn default() -> Self { Self::new() } } impl Hash for Set { fn hash(&self, state: &mut H) { self.len().hash(state); let sum = self .iter() .map(get_hash) .fold(0usize, |acc, x| acc.wrapping_add(x)); sum.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(), } } pub fn get_by(&self, value: &Q, cmp: impl Fn(&Q, &Q) -> bool) -> Option<&T> where T: Borrow, Q: ?Sized, { self.elems.iter().find(|&v| cmp(v.borrow(), value)) } 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() } pub fn to_vec(&self) -> Vec where T: Clone, { self.iter().cloned().collect() } pub fn into_vec(self) -> Vec { self.elems.into_iter().collect() } } impl IntoIterator for Set { type Item = T; type IntoIter = as IntoIterator>::IntoIter; #[inline] fn into_iter(self) -> Self::IntoIter { self.elems.into_iter() } } impl<'a, T> IntoIterator for &'a Set { type Item = &'a T; type IntoIter = Iter<'a, T>; #[inline] fn into_iter(self) -> Iter<'a, T> { self.elems.iter() } } impl Set { pub fn linear_get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: ?Sized + Eq, { self.elems.iter().find(|x| (*x).borrow() == value) } pub fn linear_contains(&self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Eq, { self.elems.iter().any(|x| (*x).borrow() == value) } pub fn linear_eq(&self, other: &Set) -> bool { self.len() == other.len() && self.iter().all(|x| other.linear_contains(x)) } pub fn linear_remove(&mut self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Eq, { let mut found = false; self.elems.retain(|x| { let eq = (*x).borrow() == value; if eq { found = true; } !eq }); found } pub fn linear_exclude(mut self, other: &T) -> Set { self.linear_remove(other); self } } impl Set { #[inline] pub fn get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: ?Sized + Hash + Eq, { self.elems.get(value) } #[inline] pub fn contains(&self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Hash + Eq, { self.elems.contains(value) } #[inline] pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Hash + Eq, { self.elems.remove(value) } pub fn exclude(mut self, other: &T) -> Set { self.remove(other); self } } impl Set { /// ``` /// # 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 } } impl Set { /// newly inserted: true, already present: false #[inline] pub fn insert(&mut self, value: T) -> bool { self.elems.insert(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); } #[inline] pub fn clear(&mut self) { self.elems.clear(); } #[inline] pub fn take_all(&mut self) -> Self { Self { elems: self.elems.drain().collect(), } } pub fn inplace_map T>(&mut self, f: F) { *self = self.take_all().into_iter().map(f).collect(); } } 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()) } 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) } pub fn include(mut self, other: T) -> Set { self.insert(other); self } /// ``` /// # use erg_common::set; /// assert_eq!(set!{1, 2}.product(&set!{3, 4}), set!{(&1, &3), (&1, &4), (&2, &3), (&2, &4)}); /// ``` pub fn product<'l, 'r, U: Hash + Eq>(&'l self, other: &'r Set) -> Set<(&'l T, &'r U)> { let mut res = set! {}; for x in self.iter() { for y in other.iter() { res.insert((x, y)); } } res } } 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") } }