diff --git a/src/grouping_map.rs b/src/grouping_map.rs index de066042d..c4c200899 100644 --- a/src/grouping_map.rs +++ b/src/grouping_map.rs @@ -2,6 +2,7 @@ use crate::{ adaptors::map::{MapSpecialCase, MapSpecialCaseFn}, + generic_containers::Map, MinMaxResult, }; use std::cmp::Ordering; @@ -109,20 +110,11 @@ where /// assert_eq!(lookup[&3], 7); /// assert_eq!(lookup.len(), 3); // The final keys are only 0, 1 and 2 /// ``` - pub fn aggregate(self, mut operation: FO) -> HashMap + pub fn aggregate(self, operation: FO) -> HashMap where FO: FnMut(Option, &K, V) -> Option, { - let mut destination_map = HashMap::new(); - - self.iter.for_each(|(key, val)| { - let acc = destination_map.remove(&key); - if let Some(op_res) = operation(acc, &key, val) { - destination_map.insert(key, op_res); - } - }); - - destination_map + self.aggregate_in(operation, HashMap::new()) } /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements @@ -605,3 +597,27 @@ where self.fold_first(|acc, _, val| acc * val) } } + +impl GroupingMap +where + I: Iterator, +{ + /// Apply [`aggregate`](Self::aggregate) with a provided empty map + /// (`BTreeMap` or `HashMap` with any hasher). + pub fn aggregate_in(self, mut operation: FO, mut map: M) -> M + where + FO: FnMut(Option, &K, V) -> Option, + M: Map, + { + debug_assert!(map.is_empty()); + + self.iter.for_each(|(key, val)| { + let acc = map.remove(&key); + if let Some(op_res) = operation(acc, &key, val) { + map.insert(key, op_res); + } + }); + + map + } +}