From dc15e5cb4f54e20c55097906f572d0efc0674b94 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet <44676486+Philippe-Cholet@users.noreply.github.com> Date: Tue, 19 Mar 2024 18:05:00 +0100 Subject: [PATCH] Reintroduce `GroupingMap[By]` with one more generic parameter This is a breaking change! However, this is mostly inferred. Note that it breaks (only) laziness tests because the `GroupingMap` object is not used (I could write any type but `u8` is one of the possible returned types). If it was used then it would have been inferred. I copied/pasted the code of old `into_grouping_map[_by]` methods, added the generic `R` and updated each function body with `_in(.., HashMap::new())`. The old types are aliases of the new ones. --- src/grouping_map.rs | 29 +++++++++++++++++++++++++++++ src/lib.rs | 38 ++++++++++++++++++++++++++++++++++++++ tests/laziness.rs | 4 ++-- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/grouping_map.rs b/src/grouping_map.rs index acf2da241..9f0220ea2 100644 --- a/src/grouping_map.rs +++ b/src/grouping_map.rs @@ -9,6 +9,35 @@ use std::cmp::Ordering; use std::iter::Iterator; use std::ops::{Add, Mul}; +#[cfg(feature = "use_std")] +pub use with_hashmap::{GroupingMap, GroupingMapBy}; + +#[cfg(feature = "use_std")] +mod with_hashmap { + use super::*; + use std::collections::HashMap; + + // This is used to infer `K` when `I::Item = (K, V)` since we can't write `I::Item.0`. + pub trait KeyValue { + type Key; + } + + impl KeyValue for (K, V) { + type Key = K; + } + + /// `GroupingMap` is an intermediate struct for efficient group-and-fold operations. + /// + /// See [`GroupingGenericMap`] for more informations. + pub type GroupingMap = + GroupingGenericMap::Item as KeyValue>::Key, R>>; + + /// `GroupingMapBy` is an intermediate struct for efficient group-and-fold operations. + /// + /// See [`GroupingGenericMap`] for more informations. + pub type GroupingMapBy = GroupingMap, R>; +} + /// A wrapper to allow for an easy [`into_grouping_map_by`](crate::Itertools::into_grouping_map_by) pub type MapForGrouping = MapSpecialCase>; diff --git a/src/lib.rs b/src/lib.rs index 9411121f2..0ce69be8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,6 +113,8 @@ pub mod structs { pub use crate::groupbylazy::{Chunk, ChunkBy, Chunks, Group, Groups, IntoChunks}; #[cfg(feature = "use_alloc")] pub use crate::grouping_map::{GroupingGenericMap, GroupingGenericMapBy}; + #[cfg(feature = "use_std")] + pub use crate::grouping_map::{GroupingMap, GroupingMapBy}; pub use crate::intersperse::{Intersperse, IntersperseWith}; #[cfg(feature = "use_alloc")] pub use crate::kmerge_impl::{KMerge, KMergeBy}; @@ -3340,6 +3342,42 @@ pub trait Itertools: Iterator { group_map::into_group_map_by(self, f) } + /// Constructs a `GroupingMap` to be used later with one of the efficient + /// group-and-fold operations it allows to perform. + /// + /// The input iterator must yield item in the form of `(K, V)` where the + /// value of type `K` will be used as key to identify the groups and the + /// value of type `V` as value for the folding operation. + /// + /// See [`GroupingGenericMap`] for more informations + /// on what operations are available. + #[cfg(feature = "use_std")] + fn into_grouping_map(self) -> GroupingMap + where + Self: Iterator + Sized, + K: Hash + Eq, + { + self.into_grouping_map_in(HashMap::new()) + } + + /// Constructs a `GroupingMap` to be used later with one of the efficient + /// group-and-fold operations it allows to perform. + /// + /// The values from this iterator will be used as values for the folding operation + /// while the keys will be obtained from the values by calling `key_mapper`. + /// + /// See [`GroupingGenericMap`] for more informations + /// on what operations are available. + #[cfg(feature = "use_std")] + fn into_grouping_map_by(self, key_mapper: F) -> GroupingMapBy + where + Self: Iterator + Sized, + K: Hash + Eq, + F: FnMut(&V) -> K, + { + self.into_grouping_map_by_in(key_mapper, HashMap::new()) + } + /// Constructs a `GroupingGenericMap` to be used later with one of the efficient /// group-and-fold operations it allows to perform. /// diff --git a/tests/laziness.rs b/tests/laziness.rs index 2ce29cb8a..c1f7d2e6c 100644 --- a/tests/laziness.rs +++ b/tests/laziness.rs @@ -229,10 +229,10 @@ must_use_tests! { } // Not iterator themselves but still lazy. into_grouping_map { - let _ = Panicking.map(|x| (x, x + 1)).into_grouping_map(); + let _ = Panicking.map(|x| (x, x + 1)).into_grouping_map::<_, _, u8>(); } into_grouping_map_by { - let _ = Panicking.into_grouping_map_by(|x| *x); + let _ = Panicking.into_grouping_map_by::<_, _, _, u8>(|x| *x); } // Macros: iproduct {