From df7720d3ca7883fddcab0e02a359984c8d50a285 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet <44676486+Philippe-Cholet@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:08:40 +0100 Subject: [PATCH] New `GroupingMap::aggregate_in` Instead of `debug_assert!(map.is_empty());` we could alternatively `map.clear();`. I have a preference for it but check it's empty is less surprising, right?! Anyway, the documentation should state one or the other. --- src/grouping_map.rs | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) 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 + } +}