Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More generic maps in GroupingMap (v2) #906

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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.
Philippe-Cholet committed Mar 19, 2024
commit dc15e5cb4f54e20c55097906f572d0efc0674b94
29 changes: 29 additions & 0 deletions src/grouping_map.rs
Original file line number Diff line number Diff line change
@@ -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<K, V> 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<I, R> =
GroupingGenericMap<I, HashMap<<<I as Iterator>::Item as KeyValue>::Key, R>>;

/// `GroupingMapBy` is an intermediate struct for efficient group-and-fold operations.
///
/// See [`GroupingGenericMap`] for more informations.
pub type GroupingMapBy<I, F, R> = GroupingMap<MapForGrouping<I, F>, R>;
}

/// A wrapper to allow for an easy [`into_grouping_map_by`](crate::Itertools::into_grouping_map_by)
pub type MapForGrouping<I, F> = MapSpecialCase<I, GroupingMapFn<F>>;

38 changes: 38 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<K, V, R>(self) -> GroupingMap<Self, R>
where
Self: Iterator<Item = (K, V)> + 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<K, V, F, R>(self, key_mapper: F) -> GroupingMapBy<Self, F, R>
where
Self: Iterator<Item = V> + 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.
///
4 changes: 2 additions & 2 deletions tests/laziness.rs
Original file line number Diff line number Diff line change
@@ -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 {