use std::borrow::Borrow; use std::collections::hash_map::{ Entry, IntoKeys, IntoValues, Iter, IterMut, Keys, Values, ValuesMut, }; use std::fmt::{self, Write}; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; use std::ops::{Index, IndexMut}; use crate::fxhash::FxHashMap; use crate::get_hash; use crate::traits::Immutable; #[macro_export] macro_rules! dict { () => { $crate::dict::Dict::new() }; ($($k: expr => $v: expr),+ $(,)?) => {{ let mut dict = $crate::dict::Dict::new(); $(dict.insert($k, $v);)+ dict }}; } #[derive(Debug, Clone)] pub struct Dict { dict: FxHashMap, } impl PartialEq for Dict { fn eq(&self, other: &Dict) -> bool { self.dict == other.dict } } impl Eq for Dict {} impl Hash for Dict { fn hash(&self, state: &mut H) { let len = self.len(); len.hash(state); if len <= 1 { for (key, val) in self.iter() { key.hash(state); val.hash(state); } } else { let mut v = self .iter() .map(|(key, val)| (get_hash(key), val)) .collect::>(); v.sort_unstable_by_key(|(h, _)| *h); for (h, val) in v.iter() { state.write_usize(*h); val.hash(state); } } } } impl fmt::Display for Dict { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = "".to_string(); for (k, v) in self.dict.iter() { write!(s, "{k}: {v}, ")?; } s.pop(); s.pop(); write!(f, "{{{s}}}") } } impl FromIterator<(K, V)> for Dict { #[inline] fn from_iter>(iter: I) -> Dict { let mut dict = Dict::new(); dict.extend(iter); dict } } impl Extend<(K, V)> for Dict { #[inline] fn extend>(&mut self, iter: I) { self.guaranteed_extend(iter); } } impl From> for Dict { #[inline] fn from(v: Vec<(K, V)>) -> Dict { v.into_iter().collect() } } impl Index<&Q> for Dict where K: Borrow, Q: Hash + Eq, { type Output = V; #[inline] fn index(&self, index: &Q) -> &V { self.dict.get(index).unwrap() } } impl IndexMut<&Q> for Dict where K: Borrow, Q: Hash + Eq, { #[inline] fn index_mut(&mut self, index: &Q) -> &mut V { self.dict.get_mut(index).unwrap() } } impl Default for Dict { fn default() -> Dict { Dict::new() } } impl Dict<&K, &V> { pub fn cloned(&self) -> Dict { self.dict .iter() .map(|(&k, &v)| (k.clone(), v.clone())) .collect() } } impl Dict { #[inline] pub fn new() -> Self { Self { dict: FxHashMap::default(), } } /// ``` /// # use erg_common::dict; /// # use erg_common::dict::Dict; /// let mut dict = Dict::with_capacity(3); /// assert_eq!(dict.capacity(), 3); /// dict.insert("a", 1); /// assert_eq!(dict.capacity(), 3); /// dict.insert("b", 2); /// dict.insert("c", 3); /// dict.insert("d", 4); /// assert_ne!(dict.capacity(), 3); /// ``` pub fn with_capacity(capacity: usize) -> Self { Self { dict: FxHashMap::with_capacity_and_hasher(capacity, Default::default()), } } #[inline] pub fn len(&self) -> usize { self.dict.len() } #[inline] pub fn is_empty(&self) -> bool { self.dict.is_empty() } #[inline] pub fn capacity(&self) -> usize { self.dict.capacity() } #[inline] pub fn keys(&self) -> Keys { self.dict.keys() } #[inline] pub fn values(&self) -> Values { self.dict.values() } #[inline] pub fn values_mut(&mut self) -> ValuesMut { self.dict.values_mut() } #[inline] pub fn into_values(self) -> IntoValues { self.dict.into_values() } #[inline] pub fn into_keys(self) -> IntoKeys { self.dict.into_keys() } #[inline] pub fn iter(&self) -> Iter { self.dict.iter() } #[inline] pub fn iter_mut(&mut self) -> IterMut { self.dict.iter_mut() } pub fn clear(&mut self) { self.dict.clear(); } /// remove all elements for which the predicate returns false pub fn retain(&mut self, f: F) where F: FnMut(&K, &mut V) -> bool, { self.dict.retain(f); } pub fn retained(mut self, f: impl FnMut(&K, &mut V) -> bool) -> Self { self.retain(f); self } pub fn get_by(&self, k: &K, cmp: impl Fn(&K, &K) -> bool) -> Option<&V> { for (k_, v) in self.dict.iter() { if cmp(k, k_) { return Some(v); } } None } } impl IntoIterator for Dict { type Item = (K, V); type IntoIter = as IntoIterator>::IntoIter; #[inline] fn into_iter(self) -> Self::IntoIter { self.dict.into_iter() } } impl<'a, K, V> IntoIterator for &'a Dict { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; #[inline] fn into_iter(self) -> Self::IntoIter { self.dict.iter() } } impl Dict { /// K: interior-mutable pub fn linear_get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Eq + ?Sized, { self.dict .iter() .find(|(k, _)| (*k).borrow() == key) .map(|(_, v)| v) } pub fn linear_get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: Eq + ?Sized, { self.dict .iter_mut() .find(|(k, _)| (*k).borrow() == key) .map(|(_, v)| v) } } impl Dict { /// K: interior-mutable pub fn linear_eq(&self, other: &Self) -> bool { if self.len() != other.len() { return false; } for (k, v) in self.iter() { if other.linear_get(k) != Some(v) { return false; } } true } } impl Dict { #[inline] pub fn get(&self, k: &Q) -> Option<&V> where K: Borrow, Q: Hash + Eq + ?Sized, { self.dict.get(k) } #[inline] pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> where K: Borrow, Q: Hash + Eq + ?Sized, { self.dict.get_mut(k) } pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Hash + Eq + ?Sized, { self.dict.get_key_value(k) } #[inline] pub fn contains_key(&self, k: &Q) -> bool where K: Borrow, Q: Hash + Eq + ?Sized, { self.dict.contains_key(k) } #[inline] pub fn remove(&mut self, k: &Q) -> Option where K: Borrow, Q: Hash + Eq + ?Sized, { self.dict.remove(k) } pub fn remove_entry(&mut self, k: &Q) -> Option<(K, V)> where K: Borrow, Q: Hash + Eq + ?Sized, { self.dict.remove_entry(k) } pub fn remove_entries<'q, Q>(&mut self, keys: impl IntoIterator) where K: Borrow, Q: Hash + Eq + ?Sized + 'q, { for k in keys { self.remove_entry(k); } } } impl Dict { #[inline] pub fn insert(&mut self, k: K, v: V) -> Option { self.dict.insert(k, v) } /// NOTE: This method does not consider pairing with values and keys. That is, a value may be paired with a different key (can be considered equal). /// If you need to consider the pairing of the keys and values, use `guaranteed_extend` instead. #[inline] pub fn extend>(&mut self, iter: I) { self.dict.extend(iter); } /// If the key already exists, the value will not be updated. #[inline] pub fn guaranteed_extend>(&mut self, other: I) { for (k, v) in other { self.dict.entry(k).or_insert(v); } } #[inline] pub fn merge(&mut self, other: Self) { self.dict.extend(other.dict); } #[inline] pub fn concat(mut self, other: Self) -> Self { self.merge(other); self } #[inline] pub fn diff(mut self, other: &Self) -> Self { for k in other.dict.keys() { self.dict.remove(k); } self } pub fn entry(&mut self, k: K) -> Entry { self.dict.entry(k) } } #[cfg(test)] mod tests { use super::*; use crate::str::Str; #[test] fn test_dict() { let mut dict = Dict::new(); dict.insert(Str::from("a"), 1); dict.insert(Str::from("b"), 2); dict.insert(Str::from("c"), 3); assert_eq!(dict.len(), 3); assert_eq!(dict.get(&Str::from("a")), Some(&1)); assert_eq!(dict.get(&Str::from("b")), Some(&2)); assert_eq!(dict.get(&Str::from("c")), Some(&3)); assert_eq!(dict.get(&Str::from("d")), None); assert_eq!(dict.get("a"), Some(&1)); assert_eq!(dict.get("b"), Some(&2)); assert_eq!(dict.get("c"), Some(&3)); assert_eq!(dict.get("d"), None); assert_eq!(dict.remove(&Str::from("a")), Some(1)); assert_eq!(dict.remove(&Str::from("a")), None); assert_eq!(dict.len(), 2); assert_eq!(dict.get(&Str::from("a")), None); assert_eq!(dict.get(&Str::from("b")), Some(&2)); assert_eq!(dict.get(&Str::from("c")), Some(&3)); assert_eq!(dict.get(&Str::from("d")), None); dict.clear(); assert_eq!(dict.len(), 0); assert_eq!(dict.get(&Str::from("a")), None); assert_eq!(dict.get(&Str::from("b")), None); assert_eq!(dict.get(&Str::from("c")), None); assert_eq!(dict.get(&Str::from("d")), None); } }