## slice-group-by

Iterators over groups in a slice

### 10 releases

 0.3.0 Oct 12, 2021 Feb 13, 2021 Jul 20, 2019 Jun 15, 2019 Jan 30, 2019

#52 in Algorithms

Used in 17 crates (3 directly)

105KB
2K SLoC

# slice-group-by

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);
``````