Skip to content

Commit 3db9c7e

Browse files
committed
Add into_grouping_map_[by_]with_hasher
1 parent 4324c14 commit 3db9c7e

File tree

2 files changed

+73
-27
lines changed

2 files changed

+73
-27
lines changed

src/grouping_map.rs

+32-25
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ use crate::{
22
adaptors::map::{MapSpecialCase, MapSpecialCaseFn},
33
MinMaxResult,
44
};
5-
use std::cmp::Ordering;
5+
use core::hash::BuildHasher;
66
use std::collections::HashMap;
77
use std::hash::Hash;
88
use std::iter::Iterator;
99
use std::ops::{Add, Mul};
10+
use std::{cmp::Ordering, hash::RandomState};
1011

1112
/// A wrapper to allow for an easy [`into_grouping_map_by`](crate::Itertools::into_grouping_map_by)
1213
pub type MapForGrouping<I, F> = MapSpecialCase<I, GroupingMapFn<F>>;
@@ -36,18 +37,19 @@ pub(crate) fn new_map_for_grouping<K, I: Iterator, F: FnMut(&I::Item) -> K>(
3637
}
3738

3839
/// Creates a new `GroupingMap` from `iter`
39-
pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
40+
pub fn new<I, K, V, S>(iter: I, hash_builder: S) -> GroupingMap<I, S>
4041
where
4142
I: Iterator<Item = (K, V)>,
4243
K: Hash + Eq,
44+
S: BuildHasher,
4345
{
44-
GroupingMap { iter }
46+
GroupingMap { iter, hash_builder }
4547
}
4648

4749
/// `GroupingMapBy` is an intermediate struct for efficient group-and-fold operations.
4850
///
4951
/// See [`GroupingMap`] for more informations.
50-
pub type GroupingMapBy<I, F> = GroupingMap<MapForGrouping<I, F>>;
52+
pub type GroupingMapBy<I, F, S = RandomState> = GroupingMap<MapForGrouping<I, F>, S>;
5153

5254
/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
5355
/// It groups elements by their key and at the same time fold each group
@@ -56,14 +58,19 @@ pub type GroupingMapBy<I, F> = GroupingMap<MapForGrouping<I, F>>;
5658
/// No method on this struct performs temporary allocations.
5759
#[derive(Clone, Debug)]
5860
#[must_use = "GroupingMap is lazy and do nothing unless consumed"]
59-
pub struct GroupingMap<I> {
61+
pub struct GroupingMap<I, S = RandomState>
62+
where
63+
S: BuildHasher,
64+
{
6065
iter: I,
66+
hash_builder: S,
6167
}
6268

63-
impl<I, K, V> GroupingMap<I>
69+
impl<I, K, V, S> GroupingMap<I, S>
6470
where
6571
I: Iterator<Item = (K, V)>,
6672
K: Hash + Eq,
73+
S: BuildHasher,
6774
{
6875
/// This is the generic way to perform any operation on a `GroupingMap`.
6976
/// It's suggested to use this method only to implement custom operations
@@ -105,11 +112,11 @@ where
105112
/// assert_eq!(lookup[&3], 7);
106113
/// assert_eq!(lookup.len(), 3); // The final keys are only 0, 1 and 2
107114
/// ```
108-
pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
115+
pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R, S>
109116
where
110117
FO: FnMut(Option<R>, &K, V) -> Option<R>,
111118
{
112-
let mut destination_map = HashMap::new();
119+
let mut destination_map = HashMap::with_hasher(self.hash_builder);
113120

114121
self.iter.for_each(|(key, val)| {
115122
let acc = destination_map.remove(&key);
@@ -154,7 +161,7 @@ where
154161
/// assert_eq!(lookup[&2].acc, 2 + 5);
155162
/// assert_eq!(lookup.len(), 3);
156163
/// ```
157-
pub fn fold_with<FI, FO, R>(self, mut init: FI, mut operation: FO) -> HashMap<K, R>
164+
pub fn fold_with<FI, FO, R>(self, mut init: FI, mut operation: FO) -> HashMap<K, R, S>
158165
where
159166
FI: FnMut(&K, &V) -> R,
160167
FO: FnMut(R, &K, V) -> R,
@@ -190,7 +197,7 @@ where
190197
/// assert_eq!(lookup[&2], 2 + 5);
191198
/// assert_eq!(lookup.len(), 3);
192199
/// ```
193-
pub fn fold<FO, R>(self, init: R, operation: FO) -> HashMap<K, R>
200+
pub fn fold<FO, R>(self, init: R, operation: FO) -> HashMap<K, R, S>
194201
where
195202
R: Clone,
196203
FO: FnMut(R, &K, V) -> R,
@@ -225,7 +232,7 @@ where
225232
/// assert_eq!(lookup[&2], 2 + 5);
226233
/// assert_eq!(lookup.len(), 3);
227234
/// ```
228-
pub fn reduce<FO>(self, mut operation: FO) -> HashMap<K, V>
235+
pub fn reduce<FO>(self, mut operation: FO) -> HashMap<K, V, S>
229236
where
230237
FO: FnMut(V, &K, V) -> V,
231238
{
@@ -239,7 +246,7 @@ where
239246

240247
/// See [`.reduce()`](GroupingMap::reduce).
241248
#[deprecated(note = "Use .reduce() instead", since = "0.13.0")]
242-
pub fn fold_first<FO>(self, operation: FO) -> HashMap<K, V>
249+
pub fn fold_first<FO>(self, operation: FO) -> HashMap<K, V, S>
243250
where
244251
FO: FnMut(V, &K, V) -> V,
245252
{
@@ -264,11 +271,11 @@ where
264271
/// assert_eq!(lookup[&2], vec![2, 5].into_iter().collect::<HashSet<_>>());
265272
/// assert_eq!(lookup.len(), 3);
266273
/// ```
267-
pub fn collect<C>(self) -> HashMap<K, C>
274+
pub fn collect<C>(self) -> HashMap<K, C, S>
268275
where
269276
C: Default + Extend<V>,
270277
{
271-
let mut destination_map = HashMap::new();
278+
let mut destination_map = HashMap::with_hasher(self.hash_builder);
272279

273280
self.iter.for_each(|(key, val)| {
274281
destination_map
@@ -298,7 +305,7 @@ where
298305
/// assert_eq!(lookup[&2], 8);
299306
/// assert_eq!(lookup.len(), 3);
300307
/// ```
301-
pub fn max(self) -> HashMap<K, V>
308+
pub fn max(self) -> HashMap<K, V, S>
302309
where
303310
V: Ord,
304311
{
@@ -324,7 +331,7 @@ where
324331
/// assert_eq!(lookup[&2], 5);
325332
/// assert_eq!(lookup.len(), 3);
326333
/// ```
327-
pub fn max_by<F>(self, mut compare: F) -> HashMap<K, V>
334+
pub fn max_by<F>(self, mut compare: F) -> HashMap<K, V, S>
328335
where
329336
F: FnMut(&K, &V, &V) -> Ordering,
330337
{
@@ -353,7 +360,7 @@ where
353360
/// assert_eq!(lookup[&2], 5);
354361
/// assert_eq!(lookup.len(), 3);
355362
/// ```
356-
pub fn max_by_key<F, CK>(self, mut f: F) -> HashMap<K, V>
363+
pub fn max_by_key<F, CK>(self, mut f: F) -> HashMap<K, V, S>
357364
where
358365
F: FnMut(&K, &V) -> CK,
359366
CK: Ord,
@@ -379,7 +386,7 @@ where
379386
/// assert_eq!(lookup[&2], 5);
380387
/// assert_eq!(lookup.len(), 3);
381388
/// ```
382-
pub fn min(self) -> HashMap<K, V>
389+
pub fn min(self) -> HashMap<K, V, S>
383390
where
384391
V: Ord,
385392
{
@@ -405,7 +412,7 @@ where
405412
/// assert_eq!(lookup[&2], 8);
406413
/// assert_eq!(lookup.len(), 3);
407414
/// ```
408-
pub fn min_by<F>(self, mut compare: F) -> HashMap<K, V>
415+
pub fn min_by<F>(self, mut compare: F) -> HashMap<K, V, S>
409416
where
410417
F: FnMut(&K, &V, &V) -> Ordering,
411418
{
@@ -434,7 +441,7 @@ where
434441
/// assert_eq!(lookup[&2], 8);
435442
/// assert_eq!(lookup.len(), 3);
436443
/// ```
437-
pub fn min_by_key<F, CK>(self, mut f: F) -> HashMap<K, V>
444+
pub fn min_by_key<F, CK>(self, mut f: F) -> HashMap<K, V, S>
438445
where
439446
F: FnMut(&K, &V) -> CK,
440447
CK: Ord,
@@ -469,7 +476,7 @@ where
469476
/// assert_eq!(lookup[&2], OneElement(5));
470477
/// assert_eq!(lookup.len(), 3);
471478
/// ```
472-
pub fn minmax(self) -> HashMap<K, MinMaxResult<V>>
479+
pub fn minmax(self) -> HashMap<K, MinMaxResult<V>, S>
473480
where
474481
V: Ord,
475482
{
@@ -499,7 +506,7 @@ where
499506
/// assert_eq!(lookup[&2], OneElement(5));
500507
/// assert_eq!(lookup.len(), 3);
501508
/// ```
502-
pub fn minmax_by<F>(self, mut compare: F) -> HashMap<K, MinMaxResult<V>>
509+
pub fn minmax_by<F>(self, mut compare: F) -> HashMap<K, MinMaxResult<V>, S>
503510
where
504511
F: FnMut(&K, &V, &V) -> Ordering,
505512
{
@@ -550,7 +557,7 @@ where
550557
/// assert_eq!(lookup[&2], OneElement(5));
551558
/// assert_eq!(lookup.len(), 3);
552559
/// ```
553-
pub fn minmax_by_key<F, CK>(self, mut f: F) -> HashMap<K, MinMaxResult<V>>
560+
pub fn minmax_by_key<F, CK>(self, mut f: F) -> HashMap<K, MinMaxResult<V>, S>
554561
where
555562
F: FnMut(&K, &V) -> CK,
556563
CK: Ord,
@@ -577,7 +584,7 @@ where
577584
/// assert_eq!(lookup[&2], 5 + 8);
578585
/// assert_eq!(lookup.len(), 3);
579586
/// ```
580-
pub fn sum(self) -> HashMap<K, V>
587+
pub fn sum(self) -> HashMap<K, V, S>
581588
where
582589
V: Add<V, Output = V>,
583590
{
@@ -603,7 +610,7 @@ where
603610
/// assert_eq!(lookup[&2], 5 * 8);
604611
/// assert_eq!(lookup.len(), 3);
605612
/// ```
606-
pub fn product(self) -> HashMap<K, V>
613+
pub fn product(self) -> HashMap<K, V, S>
607614
where
608615
V: Mul<V, Output = V>,
609616
{

src/lib.rs

+41-2
Original file line numberDiff line numberDiff line change
@@ -3921,7 +3921,21 @@ pub trait Itertools: Iterator {
39213921
Self: Iterator<Item = (K, V)> + Sized,
39223922
K: Hash + Eq,
39233923
{
3924-
grouping_map::new(self)
3924+
grouping_map::new(self, RandomState::new())
3925+
}
3926+
3927+
/// Constructs a `GroupingMap` to be used later with one of the efficient
3928+
/// group-and-fold operations it allows to perform, using the specified hash builder for
3929+
/// hashing the elements.
3930+
/// See [.into_grouping_map()](crate::Itertools::into_grouping_map) for more information.
3931+
#[cfg(feature = "use_std")]
3932+
fn into_grouping_map_with_hasher<K, V, S>(self, hash_builder: S) -> GroupingMap<Self, S>
3933+
where
3934+
Self: Iterator<Item = (K, V)> + Sized,
3935+
K: Hash + Eq,
3936+
S: BuildHasher,
3937+
{
3938+
grouping_map::new(self, hash_builder)
39253939
}
39263940

39273941
/// Constructs a `GroupingMap` to be used later with one of the efficient
@@ -3939,7 +3953,32 @@ pub trait Itertools: Iterator {
39393953
K: Hash + Eq,
39403954
F: FnMut(&V) -> K,
39413955
{
3942-
grouping_map::new(grouping_map::new_map_for_grouping(self, key_mapper))
3956+
grouping_map::new(
3957+
grouping_map::new_map_for_grouping(self, key_mapper),
3958+
RandomState::new(),
3959+
)
3960+
}
3961+
3962+
/// Constructs a `GroupingMap` to be used later with one of the efficient
3963+
/// group-and-fold operations it allows to perform, using the specified hash builder for
3964+
/// hashing the keys.
3965+
/// See [.into_grouping_map_by()](crate::Itertools::into_grouping_map_by) for more information.
3966+
#[cfg(feature = "use_std")]
3967+
fn into_grouping_map_by_with_hasher<K, V, F, S>(
3968+
self,
3969+
key_mapper: F,
3970+
hash_builder: S,
3971+
) -> GroupingMapBy<Self, F, S>
3972+
where
3973+
Self: Iterator<Item = V> + Sized,
3974+
K: Hash + Eq,
3975+
F: FnMut(&V) -> K,
3976+
S: BuildHasher,
3977+
{
3978+
grouping_map::new(
3979+
grouping_map::new_map_for_grouping(self, key_mapper),
3980+
hash_builder,
3981+
)
39433982
}
39443983

39453984
/// Return all minimum elements of an iterator.

0 commit comments

Comments
 (0)