Skip to content

Commit b5eb398

Browse files
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.
1 parent 4331f41 commit b5eb398

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

src/grouping_map.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use crate::{
44
adaptors::map::{MapSpecialCase, MapSpecialCaseFn},
5+
generic_containers::Map,
56
MinMaxResult,
67
};
78
use std::cmp::Ordering;
@@ -109,20 +110,11 @@ where
109110
/// assert_eq!(lookup[&3], 7);
110111
/// assert_eq!(lookup.len(), 3); // The final keys are only 0, 1 and 2
111112
/// ```
112-
pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
113+
pub fn aggregate<FO, R>(self, operation: FO) -> HashMap<K, R>
113114
where
114115
FO: FnMut(Option<R>, &K, V) -> Option<R>,
115116
{
116-
let mut destination_map = HashMap::new();
117-
118-
self.iter.for_each(|(key, val)| {
119-
let acc = destination_map.remove(&key);
120-
if let Some(op_res) = operation(acc, &key, val) {
121-
destination_map.insert(key, op_res);
122-
}
123-
});
124-
125-
destination_map
117+
self.aggregate_in(operation, HashMap::new())
126118
}
127119

128120
/// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
@@ -614,3 +606,27 @@ where
614606
self.reduce(|acc, _, val| acc * val)
615607
}
616608
}
609+
610+
impl<I, K, V> GroupingMap<I>
611+
where
612+
I: Iterator<Item = (K, V)>,
613+
{
614+
/// Apply [`aggregate`](Self::aggregate) with a provided empty map
615+
/// (`BTreeMap` or `HashMap` with any hasher).
616+
pub fn aggregate_in<FO, R, M>(self, mut operation: FO, mut map: M) -> M
617+
where
618+
FO: FnMut(Option<R>, &K, V) -> Option<R>,
619+
M: Map<Key = K, Value = R>,
620+
{
621+
debug_assert!(map.is_empty());
622+
623+
self.iter.for_each(|(key, val)| {
624+
let acc = map.remove(&key);
625+
if let Some(op_res) = operation(acc, &key, val) {
626+
map.insert(key, op_res);
627+
}
628+
});
629+
630+
map
631+
}
632+
}

0 commit comments

Comments
 (0)