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 {