Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Ockajak committed Jul 12, 2024
1 parent dbd664b commit 6a3aea5
Show file tree
Hide file tree
Showing 15 changed files with 175 additions and 89 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ data.group_by(|x| x % 2); // HashMap::from([(0, vec![2]), (1, vec![1, 3]
| *frequencies* | :heavy_check_mark: | :heavy_check_mark: | | |
| *frequencies_by* | :heavy_check_mark: | :heavy_check_mark: | | |
| *group_by* | :heavy_check_mark: | | :heavy_check_mark: | |
| *group_fold* | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: |
| *group_fold* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | |
| *group_fold_to* | :heavy_check_mark: | | :heavy_check_mark: | |
| *group_reduce* | :heavy_check_mark: | | :heavy_check_mark: | |
| *interleave* | :heavy_check_mark: | | | |
| *interleave_shortest* | :heavy_check_mark: | | | |
Expand Down
27 changes: 14 additions & 13 deletions src/extensions/collectible.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::extensions::collect_by_index;
use crate::extensions::iterable::Iterable;
use crate::extensions::util::unfold::unfold;
use std::cmp::Reverse;
use std::collections::{BinaryHeap, HashMap, HashSet};
use std::hash::Hash;
use std::iter;
use std::iter::{Product, Sum};
use crate::extensions::collect_by_index;

/// Consuming collection operations.
///
Expand Down Expand Up @@ -703,24 +703,29 @@ pub trait Collectible<Item>: IntoIterator<Item = Item> {
/// The folding operation takes an accumulator and a closure and returns a new element.
/// The closure returns the value that the accumulator should have for the next iteration.
///
/// This is a consuming variant of [`group_fold`].
///
/// [`group_fold`]: Traversable::group_fold
///
/// ```
/// use crate::cantrip::*;
/// use std::collections::HashMap;
///
/// let a = vec![1, 2, 3];
///
/// let group_folded = a.group_fold(|x| x % 2, 0, |acc, x| acc + x);
/// let group_folded = a.group_fold_to(|x| x % 2, 0, |acc, x| acc + x);
///
/// assert_eq!(group_folded, HashMap::from([
/// (0, 2),
/// (1, 4),
/// ]));
/// ```
#[allow(unused_results)]
fn group_fold<K: Eq + Hash, B>(
fn group_fold_to<K, B>(
self, mut to_key: impl FnMut(&Item) -> K, initial_value: B, mut function: impl FnMut(B, Item) -> B,
) -> HashMap<K, B>
where
K: Eq + Hash,
B: Clone,
Self: Sized,
{
Expand Down Expand Up @@ -1304,11 +1309,9 @@ pub trait Collectible<Item>: IntoIterator<Item = Item> {
}

#[inline]
pub(crate) fn combinations<'a, Item, Collection>(iterator: impl Iterator<Item = &'a Item>, k: usize) -> Vec<Collection>
where
Item: Clone + 'a,
Collection: FromIterator<Item> + Sized,
{
pub(crate) fn combinations<'a, Item: Clone + 'a, Collection: FromIterator<Item> + Sized>(
iterator: impl Iterator<Item = &'a Item>, k: usize,
) -> Vec<Collection> {
let values = Vec::from_iter(iterator);
compute_combinations(&values, k)
}
Expand Down Expand Up @@ -1353,11 +1356,9 @@ pub(crate) fn partition_map<'a, Item: 'a, A, B, Left: Default + Extend<A>, Right
(result_left, result_right)
}

pub(crate) fn powerset<'a, Item, Collection>(iterator: impl Iterator<Item = &'a Item>) -> Vec<Collection>
where
Item: Clone + 'a,
Collection: FromIterator<Item> + Sized,
{
pub(crate) fn powerset<'a, Item: Clone + 'a, Collection: FromIterator<Item> + Sized>(
iterator: impl Iterator<Item = &'a Item>,
) -> Vec<Collection> {
let values = Vec::from_iter(iterator);
let sizes = 1..=values.len();
iter::once(Collection::from_iter(iter::empty()))
Expand Down
13 changes: 12 additions & 1 deletion src/extensions/collections/binary_heap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::collections::{BinaryHeap, HashMap};
use std::hash::Hash;
use crate::extensions::*;

Expand Down Expand Up @@ -34,6 +34,17 @@ impl<Item> Traversable<Item> for BinaryHeap<Item> {
self.iter().fold(initial_value, function)
}

#[inline]
fn group_fold<K, B>(
&self, to_key: impl FnMut(&Item) -> K, initial_value: B, function: impl FnMut(B, &Item) -> B,
) -> HashMap<K, B>
where
K: Eq + Hash,
B: Clone,
{
group_fold(self.iter(), to_key, initial_value, function)
}

#[inline]
fn max_by(&self, mut compare: impl FnMut(&Item, &Item) -> Ordering) -> Option<&Item> {
self.iter().max_by(|&x, &y| compare(x, y))
Expand Down
13 changes: 12 additions & 1 deletion src/extensions/collections/btree_set.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::extensions::*;
use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::collections::{BTreeSet, HashMap};
use std::hash::Hash;

impl<Item> Traversable<Item> for BTreeSet<Item> {
Expand Down Expand Up @@ -34,6 +34,17 @@ impl<Item> Traversable<Item> for BTreeSet<Item> {
self.iter().fold(initial_value, function)
}

#[inline]
fn group_fold<K, B>(
&self, to_key: impl FnMut(&Item) -> K, initial_value: B, function: impl FnMut(B, &Item) -> B,
) -> HashMap<K, B>
where
K: Eq + Hash,
B: Clone,
{
group_fold(self.iter(), to_key, initial_value, function)
}

#[inline]
fn max_by(&self, mut compare: impl FnMut(&Item, &Item) -> Ordering) -> Option<&Item> {
self.iter().max_by(|&x, &y| compare(x, y))
Expand Down
13 changes: 12 additions & 1 deletion src/extensions/collections/hash_set.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::cmp::Ordering;
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use std::hash::Hash;

use crate::extensions::*;
Expand Down Expand Up @@ -35,6 +35,17 @@ impl<Item> Traversable<Item> for HashSet<Item> {
self.iter().fold(initial_value, function)
}

#[inline]
fn group_fold<K, B>(
&self, to_key: impl FnMut(&Item) -> K, initial_value: B, function: impl FnMut(B, &Item) -> B,
) -> HashMap<K, B>
where
K: Eq + Hash,
B: Clone,
{
group_fold(self.iter(), to_key, initial_value, function)
}

#[inline]
fn max_by(&self, mut compare: impl FnMut(&Item, &Item) -> Ordering) -> Option<&Item> {
self.iter().max_by(|&x, &y| compare(x, y))
Expand Down
11 changes: 11 additions & 0 deletions src/extensions/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ impl<Item> Traversable<Item> for LinkedList<Item> {
self.iter().fold(initial_value, function)
}

#[inline]
fn group_fold<K, B>(
&self, to_key: impl FnMut(&Item) -> K, initial_value: B, function: impl FnMut(B, &Item) -> B,
) -> HashMap<K, B>
where
K: Eq + Hash,
B: Clone,
{
group_fold(self.iter(), to_key, initial_value, function)
}

#[inline]
fn max_by(&self, mut compare: impl FnMut(&Item, &Item) -> Ordering) -> Option<&Item> {
self.iter().max_by(|&x, &y| compare(x, y))
Expand Down
11 changes: 11 additions & 0 deletions src/extensions/collections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ impl<Item> Traversable<Item> for [Item] {
self.iter().fold(initial_value, function)
}

#[inline]
fn group_fold<K, B>(
&self, to_key: impl FnMut(&Item) -> K, initial_value: B, function: impl FnMut(B, &Item) -> B,
) -> HashMap<K, B>
where
K: Eq + Hash,
B: Clone,
{
group_fold(self.iter(), to_key, initial_value, function)
}

#[inline]
fn max_by(&self, mut compare: impl FnMut(&Item, &Item) -> Ordering) -> Option<&Item> {
self.iter().max_by(|&x, &y| compare(x, y))
Expand Down
11 changes: 11 additions & 0 deletions src/extensions/collections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ impl<Item> Traversable<Item> for Vec<Item> {
self.iter().fold(initial_value, function)
}

#[inline]
fn group_fold<K, B>(
&self, to_key: impl FnMut(&Item) -> K, initial_value: B, function: impl FnMut(B, &Item) -> B,
) -> HashMap<K, B>
where
K: Eq + Hash,
B: Clone,
{
group_fold(self.iter(), to_key, initial_value, function)
}

#[inline]
fn max_by(&self, mut compare: impl FnMut(&Item, &Item) -> Ordering) -> Option<&Item> {
self.iter().max_by(|&x, &y| compare(x, y))
Expand Down
11 changes: 11 additions & 0 deletions src/extensions/collections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ impl<Item> Traversable<Item> for VecDeque<Item> {
self.iter().fold(initial_value, function)
}

#[inline]
fn group_fold<K, B>(
&self, to_key: impl FnMut(&Item) -> K, initial_value: B, function: impl FnMut(B, &Item) -> B,
) -> HashMap<K, B>
where
K: Eq + Hash,
B: Clone,
{
group_fold(self.iter(), to_key, initial_value, function)
}

#[inline]
fn max_by(&self, mut compare: impl FnMut(&Item, &Item) -> Ordering) -> Option<&Item> {
self.iter().max_by(|&x, &y| compare(x, y))
Expand Down
4 changes: 2 additions & 2 deletions src/extensions/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/// - May create a new collection
///
pub trait List<Item> {
/// Returns the first element of the slice, or `None` if it is empty.
/// Returns the first element of this sequence, or `None` if it is empty.
///
/// # Examples
///
Expand All @@ -21,7 +21,7 @@ pub trait List<Item> {
/// ```
fn first(&self) -> Option<&Item>;

/// Returns the last element of the slice, or `None` if it is empty.
/// Returns the last element of this sequence, or `None` if it is empty.
///
/// # Examples
///
Expand Down
6 changes: 2 additions & 4 deletions src/extensions/map.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::extensions::iterable::Iterable;
use std::cmp::Ordering;
use std::collections::HashSet;
use std::hash::Hash;
use std::iter;
use std::iter::{Product, Sum};
use crate::extensions::iterable::Iterable;

/// Map operations.
///
Expand Down Expand Up @@ -1931,12 +1931,10 @@ pub(crate) fn minmax_by_key_pairs<'a, K: 'a, V: 'a, E: Ord>(
minmax_by_pairs(iterator, |x, y| to_key(x).cmp(&to_key(y)))
}

pub(crate) fn partition_map_pairs<'a, K, V, L1, W1, L2, W2, Left, Right>(
pub(crate) fn partition_map_pairs<'a, K: 'a, V: 'a, L1, W1, L2, W2, Left, Right>(
iterator: impl Iterator<Item = (&'a K, &'a V)>, mut function: impl FnMut((&K, &V)) -> Result<(L1, W1), (L2, W2)>,
) -> (Left, Right)
where
K: 'a,
V: 'a,
Left: Default + Extend<(L1, W1)>,
Right: Default + Extend<(L2, W2)>,
{
Expand Down
26 changes: 6 additions & 20 deletions src/extensions/ordered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,11 +469,9 @@ pub trait Ordered<Item> {
fn rposition(&self, predicate: impl FnMut(&Item) -> bool) -> Option<usize>;
}

pub(crate) fn common_prefix_length<'a, Item>(
pub(crate) fn common_prefix_length<'a, Item: PartialEq + 'a>(
iterator: impl Iterator<Item = &'a Item>, elements: &'a impl Iterable<Item<'a> = &'a Item>,
) -> usize
where
Item: PartialEq + 'a,
{
let mut result = 0_usize;
for (item, element) in iterator.zip(elements.iterator()) {
Expand All @@ -485,12 +483,9 @@ where
result
}

pub(crate) fn common_suffix_length<'a, Item, I>(
pub(crate) fn common_suffix_length<'a, Item: PartialEq + 'a, I: DoubleEndedIterator<Item = &'a Item>>(
reversed_iterator: impl Iterator<Item = &'a Item>, elements: &'a impl Iterable<Item<'a> = &'a Item, Iterator<'a> = I>,
) -> usize
where
I: DoubleEndedIterator<Item = &'a Item>,
Item: PartialEq + 'a,
{
let mut result = 0_usize;
for (item, element) in reversed_iterator.zip(elements.iterator().rev()) {
Expand All @@ -508,11 +503,9 @@ pub(crate) fn count_unique<'a, Item: Eq + Hash + 'a>(iterator: impl Iterator<Ite
items.len()
}

pub(crate) fn equivalent<'a, Item>(
pub(crate) fn equivalent<'a, Item: Eq + Hash + 'a>(
iterator: impl Iterator<Item = &'a Item>, elements: &'a impl Iterable<Item<'a> = &'a Item>,
) -> bool
where
Item: Eq + Hash + 'a,
{
let elements_iterator = elements.iterator();
let mut excluded: HashMap<&Item, usize> = HashMap::with_capacity(iterator.size_hint().0);
Expand All @@ -537,12 +530,9 @@ where
remaining == 0
}

pub(crate) fn frequencies_by<'a, Item, K>(
pub(crate) fn frequencies_by<'a, Item: 'a, K: Eq + Hash>(
iterator: impl Iterator<Item = &'a Item>, mut to_key: impl FnMut(&Item) -> K,
) -> HashMap<K, usize>
where
Item: 'a,
K: Eq + Hash,
{
let mut result = HashMap::with_capacity(iterator.size_hint().0);
for item in iterator {
Expand Down Expand Up @@ -570,20 +560,16 @@ pub(crate) fn join_items<'a, Item: Display + 'a>(
}

#[inline]
pub(crate) fn positions<'a, Item>(
pub(crate) fn positions<'a, Item: 'a>(
iterator: impl Iterator<Item = &'a Item>, mut predicate: impl FnMut(&Item) -> bool,
) -> Vec<usize>
where
Item: 'a,
{
iterator.enumerate().filter(|(_, item)| predicate(item)).map(|(index, _)| index).collect()
}

pub(crate) fn position_sequence<'a, Item>(
pub(crate) fn position_sequence<'a, Item: PartialEq + 'a>(
mut iterator: impl Iterator<Item = &'a Item>, elements: &'a impl Iterable<Item<'a> = &'a Item>,
) -> Option<usize>
where
Item: PartialEq + 'a,
{
let mut elements_iterator = elements.iterator();
if let Some(first_element) = elements_iterator.next() {
Expand Down
Loading

0 comments on commit 6a3aea5

Please sign in to comment.