#slice #string #group

no-std slice-group-by

Iterators over groups in slices and strs

11 releases

0.3.1 May 3, 2023
0.3.0 Oct 12, 2021
0.2.7 Feb 13, 2021
0.2.6 Jul 20, 2019
0.1.0 Jan 30, 2019

#49 in Algorithms

Download history 130241/week @ 2024-12-05 120290/week @ 2024-12-12 91580/week @ 2024-12-19 63836/week @ 2024-12-26 101874/week @ 2025-01-02 123685/week @ 2025-01-09 115437/week @ 2025-01-16 130058/week @ 2025-01-23 118298/week @ 2025-01-30 130322/week @ 2025-02-06 125019/week @ 2025-02-13 122642/week @ 2025-02-20 114641/week @ 2025-02-27 127627/week @ 2025-03-06 144914/week @ 2025-03-13 125561/week @ 2025-03-20

533,978 downloads per month
Used in 481 crates (10 directly)

MIT license

110KB
2.5K SLoC

slice-group-by

slice-group-by crate slice-group-by documentation dependency status build & tests worflow License

An implementation of the groupBy Haskell function, providing tools for efficiently iterating over slice and str by groups defined by a function that specifies if two elements are in the same group.

Differences with Itertools::group_by

The Itertools::group_by method use a key to compare elements, this library works like, say, slice::sort_by, it uses a comparison function. It works on every Iterator type, slice-group-by work only with slice and str, which is the power of this library, it is fast thanks to data locality.

Also slice-group-by support multiple search algorithms (i.e. linear, binary and exponential search) and can return groups starting from the end.

Examples

Linear Searched Immutable Groups

You will only need to define a function that returns true if two elements are in the same group.

The LinearGroupBy iterator will always gives contiguous elements to the predicate function.

use slice_group_by::GroupBy;

let slice = &[1, 1, 1, 3, 3, 2, 2, 2];

let mut iter = slice.linear_group_by(|a, b| a == b);

assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
assert_eq!(iter.next(), Some(&[3, 3][..]));
assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
assert_eq!(iter.next(), None);

Linear Searched Immutable Str Groups

You will only need to define a function that returns true if two char are in the same group.

The LinearStrGroupBy iterator will always gives contiguous char to the predicate function.

use slice_group_by::StrGroupBy;

let string = "aaaabbbbb饰饰cccc";

let mut iter = string.linear_group_by(|a, b| a == b);

assert_eq!(iter.next(), Some("aaaa"));
assert_eq!(iter.next(), Some("bbbbb"));
assert_eq!(iter.next(), Some("饰饰"));
assert_eq!(iter.next(), Some("cccc"));
assert_eq!(iter.next(), None);

Binary Searched Mutable Groups

It is also possible to get mutable non overlapping groups of a slice.

The BinaryGroupBy/Mut and ExponentialGroupBy/Mut iterators will not necessarily gives contiguous elements to the predicate function. The predicate function should implement an order consistent with the sort order of the slice.

use slice_group_by::GroupByMut;

let slice = &mut [1, 1, 1, 2, 2, 2, 3, 3];

let mut iter = slice.binary_group_by_mut(|a, b| a == b);

assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
assert_eq!(iter.next(), Some(&mut [3, 3][..]));
assert_eq!(iter.next(), None);

Exponential Searched Mutable Groups starting from the End

It is also possible to get mutable non overlapping groups of a slice even starting from end of it.

use slice_group_by::GroupByMut;

let slice = &mut [1, 1, 1, 2, 2, 2, 3, 3];

let mut iter = slice.exponential_group_by_mut(|a, b| a == b).rev();

assert_eq!(iter.next(), Some(&mut [3, 3][..]));
assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
assert_eq!(iter.next(), None);

No runtime deps