pub trait SequenceTo<Item>where
for<'i> &'i Self: IntoIterator<Item = &'i Item>,{
type This<I>;
Show 58 methods
// Required methods
fn add_at(self, index: usize, element: Item) -> Self;
fn add_at_multi(
self,
index: usize,
elements: impl IntoIterator<Item = Item>,
) -> Self;
fn delete_at(self, index: usize) -> Self;
fn init(self) -> Self;
fn move_at(self, source_index: usize, target_index: usize) -> Self;
fn substitute_at(self, index: usize, replacement: Item) -> Self;
fn substitute_at_multi(
self,
indices: impl IntoIterator<Item = usize>,
replacements: impl IntoIterator<Item = Item>,
) -> Self;
fn swap_at(self, source_index: usize, target_index: usize) -> Self;
fn tail(self) -> Self;
// Provided methods
fn cartesian_product(&self, k: usize) -> Vec<Self>
where Self: FromIterator<Item> + Sized,
Item: Clone { ... }
fn chunked(self, size: usize) -> Vec<Self>
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn chunked_by(self, split: impl FnMut(&Item, &Item) -> bool) -> Vec<Self>
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn chunked_exact(self, size: usize) -> Vec<Self>
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn coalesce(
self,
function: impl FnMut(Item, Item) -> Result<Item, (Item, Item)>,
) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn combinations_multi(&self, k: usize) -> Vec<Self>
where Self: FromIterator<Item> + Sized,
Item: Clone { ... }
fn delete_at_multi(self, indices: impl IntoIterator<Item = usize>) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn divide(self, separator: &Item) -> Vec<Self>
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
Item: PartialEq { ... }
fn divide_by(self, separator: impl FnMut(&Item) -> bool) -> Vec<Self>
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn duplicates(self) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
Item: Eq + Hash { ... }
fn duplicates_by<K>(self, to_key: impl FnMut(&Item) -> K) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
K: Eq + Hash { ... }
fn enumerate(self) -> Self::This<(usize, Item)>
where Self: IntoIterator<Item = Item> + Sized,
Self::This<(usize, Item)>: FromIterator<(usize, Item)> { ... }
fn fill(element: Item, size: usize) -> Self
where Self: FromIterator<Item>,
Item: Clone { ... }
fn interleave(self, elements: impl IntoIterator<Item = Item>) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn interleave_exact(self, elements: impl IntoIterator<Item = Item>) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn intersperse(self, interval: usize, element: Item) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
Item: Clone { ... }
fn intersperse_with(
self,
interval: usize,
to_value: impl FnMut() -> Item,
) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
Item: Clone { ... }
fn map_while<B>(
&self,
predicate: impl FnMut(&Item) -> Option<B>,
) -> Self::This<B>
where Self::This<B>: FromIterator<B> { ... }
fn merge(self, elements: impl IntoIterator<Item = Item>) -> Self
where Item: Ord,
Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn merge_by(
self,
elements: impl IntoIterator<Item = Item>,
compare: impl FnMut(&Item, &Item) -> Ordering,
) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn pad_left(self, size: usize, element: Item) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item>,
Item: Clone { ... }
fn pad_left_with(
self,
size: usize,
to_element: impl FnMut(usize) -> Item,
) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item>,
Item: Clone { ... }
fn pad_right(self, size: usize, element: Item) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
Item: Clone { ... }
fn pad_right_with(
self,
size: usize,
to_element: impl FnMut(usize) -> Item,
) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
Item: Clone { ... }
fn rev(self) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: DoubleEndedIterator<Item = Item> { ... }
fn rfold<B, I>(
self,
initial_value: B,
function: impl FnMut(B, Item) -> B,
) -> B
where Self: IntoIterator<Item = Item, IntoIter = I> + Sized,
I: DoubleEndedIterator<Item = Item> { ... }
fn scan<S, B>(
self,
initial_state: S,
function: impl FnMut(&mut S, Item) -> Option<B>,
) -> Self::This<B>
where Self: IntoIterator<Item = Item> + Sized,
Self::This<B>: FromIterator<B> { ... }
fn scan_ref<S, B>(
&self,
initial_state: S,
function: impl FnMut(&mut S, &Item) -> Option<B>,
) -> Self::This<B>
where Self::This<B>: FromIterator<B> { ... }
fn skip(self, n: usize) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn skip_while(self, predicate: impl FnMut(&Item) -> bool) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn slice(self, start_index: usize, end_index: usize) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item> { ... }
fn sorted(self) -> Self
where Item: Ord,
Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn sorted_by(self, compare: impl FnMut(&Item, &Item) -> Ordering) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn sorted_by_cached_key<K: Ord>(
self,
to_key: impl FnMut(&Item) -> K,
) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn sorted_by_key<K: Ord>(self, to_key: impl FnMut(&Item) -> K) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn sorted_unstable(self) -> Self
where Item: Ord,
Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn sorted_unstable_by(
self,
compare: impl FnMut(&Item, &Item) -> Ordering,
) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn sorted_unstable_by_key<K: Ord>(
self,
to_key: impl FnMut(&Item) -> K,
) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn step_by(self, step: usize) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn take(self, n: usize) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn take_while(self, predicate: impl FnMut(&Item) -> bool) -> Self
where Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn unique(self) -> Self
where Item: Eq + Hash + Clone,
Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn unique_by<K>(self, to_key: impl FnMut(&Item) -> K) -> Self
where K: Eq + Hash,
Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn unzip<A, B>(self) -> (Self::This<A>, Self::This<B>)
where Self: IntoIterator<Item = (A, B)> + Sized,
Self::This<A>: Default + Extend<A>,
Self::This<B>: Default + Extend<B> { ... }
fn variations(&self, k: usize) -> Vec<Self>
where Item: Clone,
Self: FromIterator<Item> + Sized { ... }
fn windowed(&self, size: usize, step: usize) -> Vec<Self>
where Item: Clone,
Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn windowed_circular(&self, size: usize, step: usize) -> Vec<Self>
where Item: Clone,
Self: IntoIterator<Item = Item> + FromIterator<Item> { ... }
fn zip<T>(
self,
elements: impl IntoIterator<Item = T>,
) -> Self::This<(Item, T)>
where Self: IntoIterator<Item = Item> + Sized,
Self::This<(Item, T)>: FromIterator<(Item, T)> { ... }
fn zip_padded<T>(
self,
elements: impl IntoIterator<Item = T>,
to_left_value: impl FnMut() -> Item,
to_right_value: impl FnMut() -> T,
) -> Self::This<(Item, T)>
where Self: IntoIterator<Item = Item> + Sized,
Self::This<(Item, T)>: FromIterator<(Item, T)> { ... }
}Expand description
Sequence operations.
Methods have the following properties:
- Requires the collection to represent a sequence
- May consume the sequence and its elements
- May create a new sequence
Required Associated Types§
Required Methods§
Sourcefn add_at(self, index: usize, element: Item) -> Self
fn add_at(self, index: usize, element: Item) -> Self
Creates a new sequence by inserting an element into the specified index in this sequence.
If the specified index exceeds this sequence size, no elements are inserted.
§Panics
Panics if index is out of bounds.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.add_at(0, 4), vec![4, 1, 2, 3]);
assert_eq!(a.add_at(1, 4), vec![1, 4, 2, 3]);
assert_eq!(a.add_at(3, 4), vec![1, 2, 3, 4]);
assert_eq!(e.add_at(0, 1), vec![1]);Sourcefn add_at_multi(
self,
index: usize,
elements: impl IntoIterator<Item = Item>,
) -> Self
fn add_at_multi( self, index: usize, elements: impl IntoIterator<Item = Item>, ) -> Self
Creates a new sequence by inserting all elements of another collection into the specified index in this sequence.
If the specified index exceeds this sequence size, no elements are inserted.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.add_at_multi(0, vec![4, 5]), vec![4, 5, 1, 2, 3]);
assert_eq!(a.add_at_multi(1, vec![4, 5]), vec![1, 4, 5, 2, 3]);
assert_eq!(a.add_at_multi(3, vec![4, 5]), vec![1, 2, 3, 4, 5]);
assert_eq!(e.add_at_multi(0, vec![1, 2]), vec![1, 2]);Sourcefn delete_at(self, index: usize) -> Self
fn delete_at(self, index: usize) -> Self
Creates a new sequence by omitting an element at the specified index in this sequence.
If the specified index exceeds this sequence size, no elements are deleted.
§Panics
Panics if index is out of bounds.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.delete_at(0), vec![2, 3]);
assert_eq!(a.delete_at(1), vec![1, 3]);
assert_eq!(a.delete_at(2), vec![1, 2]);Sourcefn init(self) -> Self
fn init(self) -> Self
Creates a new sequence from this sequence without the last element.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.init(), vec![1, 2]);
assert_eq!(e.init(), vec![]);Sourcefn move_at(self, source_index: usize, target_index: usize) -> Self
fn move_at(self, source_index: usize, target_index: usize) -> Self
Creates a new sequence by moving an element at an index into the specified index in this sequence.
If the target index exceeds this sequence size, the element is only removed. If the source index exceeds this sequence size, no elements are moved.
§Panics
Panics if source_index or target_index are out of bounds.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.move_at(0, 2), vec![2, 3, 1]);
assert_eq!(a.move_at(2, 1), vec![1, 3, 2]);
assert_eq!(a.move_at(1, 1), vec![1, 2, 3]);Sourcefn substitute_at(self, index: usize, replacement: Item) -> Self
fn substitute_at(self, index: usize, replacement: Item) -> Self
Creates a new sequence by replacing an element at the specified index in this sequence.
If the specified index exceeds this sequence size, no elements are replaced.
§Panics
Panics if index is out of bounds.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.substitute_at(1, 4), vec![1, 4, 3]);Sourcefn substitute_at_multi(
self,
indices: impl IntoIterator<Item = usize>,
replacements: impl IntoIterator<Item = Item>,
) -> Self
fn substitute_at_multi( self, indices: impl IntoIterator<Item = usize>, replacements: impl IntoIterator<Item = Item>, ) -> Self
Creates a new sequence by replacing all elements at specified indices in this sequence by elements from another collection.
If the specified index exceeds this sequence size, no elements are replaced.
§Panics
Panics if any of the indices is out of bounds.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.substitute_at_multi(vec![0, 2], vec![4, 5]), vec![4, 2, 5]);
assert_eq!(a.substitute_at_multi(vec![0, 2], vec![4]), vec![4, 2, 3]);
assert_eq!(a.substitute_at_multi(vec![0, 2], vec![4, 5, 6]), vec![4, 2, 5]);Sourcefn swap_at(self, source_index: usize, target_index: usize) -> Self
fn swap_at(self, source_index: usize, target_index: usize) -> Self
Creates a new sequence by swapping elements at specified indices in this sequence.
If one of the indices exceeds this sequence size, the element is only removed. If both indices exceed this sequence size, no elements are swapped.
§Panics
Panics if source_index or target_index are out of bounds.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.swap_at(0, 2), vec![3, 2, 1]);
assert_eq!(a.swap_at(1, 1), vec![1, 2, 3]);Provided Methods§
Sourcefn cartesian_product(&self, k: usize) -> Vec<Self>
fn cartesian_product(&self, k: usize) -> Vec<Self>
Creates a new sequence containing tuples for k-fold cartesian product of specified size from the elements of this sequence.
Members are generated based on element positions, not values.
Therefore, if this sequence contains duplicate elements, the resulting tuples will too.
To obtain cartesian product of unique elements, use unique().cartesian_product().
The order or tuple values is preserved.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.cartesian_product(0), vec![vec![]]);
assert_eq!(a.cartesian_product(1), vec![vec![1], vec![2], vec![3]]);
assert_eq!(a.cartesian_product(2), vec![
vec![1, 1],
vec![1, 2],
vec![1, 3],
vec![2, 1],
vec![2, 2],
vec![2, 3],
vec![3, 1],
vec![3, 2],
vec![3, 3],
]);
assert_eq!(e.cartesian_product(2), Vec::<Vec<i32>>::new());Sourcefn chunked(self, size: usize) -> Vec<Self>where
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn chunked(self, size: usize) -> Vec<Self>where
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by splitting elements of this sequence
into non-overlapping subsequences of specified size.
The chunks are sequences and do not overlap. If size does not divide
the length of the slice, then the last chunk will not have length size.
See chunked_exact() for a variant of this function that returns chunks of
always exactly chunk_size elements.
§Panics
Panics if chunk size is 0.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.chunked(2), vec![vec![1, 2], vec![3]]);
assert_eq!(a.chunked(3), vec![vec![1, 2, 3]]);
assert_eq!(a.chunked(1), vec![vec![1], vec![2], vec![3]]);Sourcefn chunked_by(self, split: impl FnMut(&Item, &Item) -> bool) -> Vec<Self>where
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn chunked_by(self, split: impl FnMut(&Item, &Item) -> bool) -> Vec<Self>where
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by splitting this sequence into non-overlapping subsequences according to the specified separator predicate.
The split predicate is called for every pair of consecutive elements,
meaning that it is called on slice[0] and slice[1],
followed by slice[1] and slice[2], and so on.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
let chunked_by = a.chunked_by(|&p, &n| p > 0 && n > 2);
assert_eq!(chunked_by, vec![vec![1, 2], vec![3]]);
let a = a_source.clone();
assert_eq!(a.chunked_by(|_, _| false), vec![vec![1, 2, 3]]);
let a = a_source.clone();
assert_eq!(a.chunked_by(|_, _| true), vec![vec![1], vec![2], vec![3]]);
assert_eq!(e.chunked_by(|_, _| true), Vec::<Vec<i32>>::new());Sourcefn chunked_exact(self, size: usize) -> Vec<Self>where
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn chunked_exact(self, size: usize) -> Vec<Self>where
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by splitting elements of this sequence
into non-overlapping subsequences of specified size.
The chunks are sequences and do not overlap. If size does not divide
the length of the slice, then the last up to size-1 elements will be omitted.
Due to each chunk having exactly chunk_size elements, the compiler can often optimize the
resulting code better than in the case of chunked().
See chunked() for a variant of this function that also returns the remainder as a smaller chunk.
§Panics
Panics if chunk size is 0.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.chunked_exact(2), vec![vec![1, 2]]);
assert_eq!(a.chunked_exact(3), vec![vec![1, 2, 3]]);
assert_eq!(a.chunked_exact(1), vec![vec![1], vec![2], vec![3]]);Sourcefn coalesce(
self,
function: impl FnMut(Item, Item) -> Result<Item, (Item, Item)>,
) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn coalesce(
self,
function: impl FnMut(Item, Item) -> Result<Item, (Item, Item)>,
) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by using the compression closure to optionally merge consecutive elements of this sequence.
The closure merge is passed two elements, previous and current and may
return either (1) Ok(merged) to merge the two values or
(2) Err((previous, current) to indicate they can’t be merged.
In (2), the value previous is included in the new sequence.
Either (1) merged or (2) current becomes the previous value
when coalesce continues with the next pair of elements to merge. The
value that remains at the end is also included in the new sequence.
use cantrip::*;
let a = vec![1, 1, 2, 1, 2, 2, 3];
let coalesced = a.coalesce(|p, n| if p % 2 == n % 2 { Ok(p + n) } else { Err((p, n)) });
assert_eq!(coalesced, vec![4, 1, 4, 3]);Sourcefn combinations_multi(&self, k: usize) -> Vec<Self>
fn combinations_multi(&self, k: usize) -> Vec<Self>
Creates a new sequence containing combinations with repetition of specified size from the elements of this sequence.
Combinations are generated based on element positions, not values.
Therefore, if this sequence contains duplicate elements, the resulting combinations will too.
To obtain a combination with repetition of unique elements, use unique().multicombinations().
The order or combination values is preserved.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.combinations_multi(0), vec![vec![]]);
assert_eq!(a.combinations_multi(1), vec![vec![1], vec![2], vec![3]]);
assert_eq!(a.combinations_multi(2), vec![
vec![1, 1],
vec![1, 2],
vec![1, 3],
vec![2, 2],
vec![2, 3],
vec![3, 3]
]);
assert_eq!(a.combinations_multi(3), vec![
vec![1, 1, 1],
vec![1, 1, 2],
vec![1, 1, 3],
vec![1, 2, 2],
vec![1, 2, 3],
vec![1, 3, 3],
vec![2, 2, 2],
vec![2, 2, 3],
vec![2, 3, 3],
vec![3, 3, 3],
]);
assert_eq!(e.combinations_multi(1), Vec::<Vec<i32>>::new());Sourcefn delete_at_multi(self, indices: impl IntoIterator<Item = usize>) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn delete_at_multi(self, indices: impl IntoIterator<Item = usize>) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by omitting elements at specified indices in this sequence.
If the specified index exceeds this sequence size, no elements are inserted.
§Panics
Panics if any of the indices is out of bounds.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.delete_at_multi(vec![0, 2]), vec![2]);
assert_eq!(a.delete_at_multi(vec![0, 1, 2]), vec![]);Sourcefn divide(self, separator: &Item) -> Vec<Self>
fn divide(self, separator: &Item) -> Vec<Self>
Creates a new sequence by splitting this sequence into subsequences separated
by elements equal to the specified separator value.
Matched elements are not contained in the subsequences.
§Examples
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.divide(&2), vec![vec![1], vec![3]]);
assert_eq!(a.divide(&0), vec![vec![1, 2, 3]]);If the first element is matched, an empty sequence will be the first element of the result. Similarly, if the last element in the sequence is matched, an empty sequence will be the last element of the result:
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.divide(&1), vec![vec![], vec![2, 3]]);If two matched elements are directly adjacent, an empty sequence will be present between them:
use cantrip::*;
let a = vec![1, 2, 2, 3];
assert_eq!(a.divide(&2), vec![vec![1], vec![], vec![3]]);Sourcefn divide_by(self, separator: impl FnMut(&Item) -> bool) -> Vec<Self>where
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn divide_by(self, separator: impl FnMut(&Item) -> bool) -> Vec<Self>where
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by splitting this sequence into subsequences separated
by elements that match the separator predicate.
Matched elements are not contained in the subsequences.
§Examples
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.divide_by(|x| x % 2 == 0), vec![vec![1], vec![3]]);If the first element is matched, an empty sequence will be the first element of the result. Similarly, if the last element in the sequence is matched, an empty sequence will be the last element of the result:
use cantrip::*;
let a = vec![1, 2, 3, 4, 5];
assert_eq!(a.divide_by(|x| x % 2 == 1), vec![vec![], vec![2], vec![4], vec![]]);If two matched elements are directly adjacent, an empty sequence will be present between them:
use cantrip::*;
let a = vec![1, 2, 2, 3];
assert_eq!(a.divide_by(|x| x % 2 == 0), vec![vec![1], vec![], vec![3]]);Sourcefn duplicates(self) -> Self
fn duplicates(self) -> Self
Creates a new collection by including only the elements of this collection that appear more than once.
Duplicates are detected using hash and equality, and each duplicate is included exactly once.
The order or duplicate values is preserved.
use cantrip::*;
let a = vec![1, 2, 2, 3];
assert_eq!(a.duplicates(), vec![2]);Sourcefn duplicates_by<K>(self, to_key: impl FnMut(&Item) -> K) -> Self
fn duplicates_by<K>(self, to_key: impl FnMut(&Item) -> K) -> Self
Creates a new collection by including only the elements of this collection that appear more than once.
Duplicates are detected by comparing the key they map to with the keying function
to_key using hash and equality, and each duplicate is included exactly once.
The order or duplicate values is preserved.
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.duplicates_by(|x| x % 2), vec![1, 3]);Sourcefn enumerate(self) -> Self::This<(usize, Item)>where
Self: IntoIterator<Item = Item> + Sized,
Self::This<(usize, Item)>: FromIterator<(usize, Item)>,
fn enumerate(self) -> Self::This<(usize, Item)>where
Self: IntoIterator<Item = Item> + Sized,
Self::This<(usize, Item)>: FromIterator<(usize, Item)>,
Creates a new sequence which contains elements of this sequence and their indices.
The new sequence contains pairs of (i, val), where i is the
current index of iteration and val is an element of this sequence.
enumerate() keeps its count as an usize. If you want to count by a
different sized integer, the zip() function provides similar
functionality.
§Overflow Behavior
The method does no guarding against overflows, so traversing more than
usize::MAX elements either produces the wrong result or panics. If
debug assertions are enabled, a panic is guaranteed.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.enumerate(), vec![(0, 1), (1, 2), (2, 3)]);Sourcefn fill(element: Item, size: usize) -> Selfwhere
Self: FromIterator<Item>,
Item: Clone,
fn fill(element: Item, size: usize) -> Selfwhere
Self: FromIterator<Item>,
Item: Clone,
Creates a new sequence containing an element specified number of times.
§Example
use cantrip::*;
assert_eq!(Vec::fill(1, 2), vec![1, 1]);
assert_eq!(Vec::fill(1, 0), vec![]);Sourcefn interleave(self, elements: impl IntoIterator<Item = Item>) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn interleave(self, elements: impl IntoIterator<Item = Item>) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Create a new sequence by interleaving the elements of this sequence with the elements of another collection.
If one sequence is longer than another, the remaining elements of the longer sequence are added to the end of the new collection.
Elements are added to the new collection in an alternating fashion. The first element comes from this sequence, the second element comes from the other collection and so on.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.interleave(vec![4, 5, 6]), vec![1, 4, 2, 5, 3, 6]);
assert_eq!(a.interleave(vec![4, 5]), vec![1, 4, 2, 5, 3]);
assert_eq!(a.interleave(vec![]), vec![1, 2, 3]);Sourcefn interleave_exact(self, elements: impl IntoIterator<Item = Item>) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn interleave_exact(self, elements: impl IntoIterator<Item = Item>) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Create a new sequence by interleaving the elements of this sequence with the elements of another collection.
If one sequence is longer than another, the remaining elements of the longer sequence are omitted.
Elements are added to the new collection in an alternating fashion. The first element comes from this sequence, the second element comes from the other collection and so on.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.interleave_exact(vec![4, 5, 6]), vec![1, 4, 2, 5, 3, 6]);
assert_eq!(a.interleave_exact(vec![4, 5]), vec![1, 4, 2, 5]);
assert_eq!(a.interleave_exact(vec![]), vec![]);Sourcefn intersperse(self, interval: usize, element: Item) -> Self
fn intersperse(self, interval: usize, element: Item) -> Self
Creates a new sequence which places a copy of separator between
elements of the original sequence with the distance between the inserted
values determined by the specified interval.
In case separator does not implement Clone or needs to be
computed every time, use intersperse_with.
§Examples
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.intersperse(1, 0), vec![1, 0, 2, 0, 3]);
assert_eq!(a.intersperse(2, 0), vec![1, 2, 0, 3]);
assert_eq!(a.intersperse(3, 0), vec![1, 2, 3]);Sourcefn intersperse_with(
self,
interval: usize,
to_value: impl FnMut() -> Item,
) -> Self
fn intersperse_with( self, interval: usize, to_value: impl FnMut() -> Item, ) -> Self
Creates a new sequence which places a value generated by to_element
between elements of the original sequence with the distance between the
inserted values determined by the specified interval.
The specified closure will be called exactly once each time an item is placed between two adjacent items from the underlying sequence. The closure is not called if the underlying sequence yields less than two items and after the last item is yielded.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.intersperse_with(1, || 0), vec![1, 0, 2, 0, 3]);
assert_eq!(a.intersperse_with(2, || 0), vec![1, 2, 0, 3]);
assert_eq!(a.intersperse_with(3, || 0), vec![1, 2, 3]);Sourcefn map_while<B>(
&self,
predicate: impl FnMut(&Item) -> Option<B>,
) -> Self::This<B>where
Self::This<B>: FromIterator<B>,
fn map_while<B>(
&self,
predicate: impl FnMut(&Item) -> Option<B>,
) -> Self::This<B>where
Self::This<B>: FromIterator<B>,
Creates a new sequence without trailing elements based on a predicate and a map the retained elements function.
map_while() takes a closure as an argument. It will call this
closure on each element of the sequence and include elements
while it returns Some(_).
§Examples
Basic usage:
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.map_while(|&x| if x < 3 { Some(x + 1) } else { None }), vec![2, 3]);Here’s the same example, but with take_while and map:
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(
a.map_ref(|&x| if x < 3 { Some(x + 1) } else { None })
.take_while(|x| x.is_some())
.map_ref(|x| x.unwrap()),
vec![2, 3]
);Sourcefn merge(self, elements: impl IntoIterator<Item = Item>) -> Self
fn merge(self, elements: impl IntoIterator<Item = Item>) -> Self
Create a new sequence by merging it with another sequence in ascending order.
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.merge(vec![0, 4, 5]), vec![0, 1, 2, 3, 4, 5]);Sourcefn merge_by(
self,
elements: impl IntoIterator<Item = Item>,
compare: impl FnMut(&Item, &Item) -> Ordering,
) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn merge_by(
self,
elements: impl IntoIterator<Item = Item>,
compare: impl FnMut(&Item, &Item) -> Ordering,
) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Create a new sequence by merging it with another sequence in ascending order with respect to the specified comparison function.
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.merge_by(vec![0, 4, 5], |l, r| l.cmp(r)), vec![0, 1, 2, 3, 4, 5]);Sourcefn pad_left(self, size: usize, element: Item) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item>,
Item: Clone,
fn pad_left(self, size: usize, element: Item) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item>,
Item: Clone,
Creates a new sequence by padding this sequence to a minimum length of size
and filling missing elements with specified value, starting from the back.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.pad_left(5, 4), vec![4, 4, 1, 2, 3]);Sourcefn pad_left_with(
self,
size: usize,
to_element: impl FnMut(usize) -> Item,
) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item>,
Item: Clone,
fn pad_left_with(
self,
size: usize,
to_element: impl FnMut(usize) -> Item,
) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item>,
Item: Clone,
Creates a new sequence by padding this sequence to a minimum length of size
and filling missing elements using a closure to_element, starting from the back.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.pad_left_with(5, |i| 2 * i), vec![0, 2, 1, 2, 3]);Sourcefn pad_right(self, size: usize, element: Item) -> Self
fn pad_right(self, size: usize, element: Item) -> Self
Creates a new sequence by padding this sequence to a minimum length of
size and filling missing elements with specified value.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.pad_right(5, 4), vec![1, 2, 3, 4, 4]);Sourcefn pad_right_with(
self,
size: usize,
to_element: impl FnMut(usize) -> Item,
) -> Self
fn pad_right_with( self, size: usize, to_element: impl FnMut(usize) -> Item, ) -> Self
Creates a new sequence by padding this sequence to a minimum length of
size and filling missing elements using a closure to_element.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.pad_right_with(5, |x| 2 * x), vec![1, 2, 3, 6, 8]);Sourcefn rev(self) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: DoubleEndedIterator<Item = Item>,
fn rev(self) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: DoubleEndedIterator<Item = Item>,
Creates a new sequence by reversing this sequence’s direction.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.rev(), vec![3, 2, 1]);Sourcefn rfold<B, I>(self, initial_value: B, function: impl FnMut(B, Item) -> B) -> B
fn rfold<B, I>(self, initial_value: B, function: impl FnMut(B, Item) -> B) -> B
Reduces this sequence’s elements to a single, final value, starting from the back.
This is the reverse version of Iterator::fold(): it takes elements
starting from the back of this sequence.
rfold() takes two arguments: an initial value, and a closure with two
arguments: an ‘accumulator’, and an element. The closure returns the value that
the accumulator should have for the next iteration.
The initial value is the value the accumulator will have on the first call.
After applying this closure to every element of this sequence, rfold()
returns the accumulator.
This operation is sometimes called ‘reduce’ or ‘inject’.
Folding is useful whenever you have a collection of something and want to produce a single value from it.
This is a consuming variant of rfold_ref().
Note: rfold() combines elements in a right-associative fashion. For associative
operators like +, the order the elements are combined in is not important, but for non-associative
operators like - the order will affect the final result.
For a left-associative version of rfold(), see fold().
§Examples
Basic usage:
use cantrip::*;
let a = vec![1, 2, 3];
// the sum of all the elements in a
assert_eq!(a.rfold_ref(0, |acc, &x| acc + x), 6);This example demonstrates the right-associative nature of rfold_to():
it builds a string, starting with an initial value
and continuing with each element from the back until the front:
use cantrip::*;
let a = vec![1, 2, 3, 4, 5];
let zero = "0".to_string();
assert_eq!(
a.rfold(zero, |acc, x| { format!("({x} + {acc})") }),
"(1 + (2 + (3 + (4 + (5 + 0)))))"
);Sourcefn scan<S, B>(
self,
initial_state: S,
function: impl FnMut(&mut S, Item) -> Option<B>,
) -> Self::This<B>
fn scan<S, B>( self, initial_state: S, function: impl FnMut(&mut S, Item) -> Option<B>, ) -> Self::This<B>
A sequence adapter which, like fold(), holds an internal state, but
unlike fold(), produces a new sequence.
scan() takes two arguments: an initial value which seeds the internal
state, and a closure with two arguments, the first being a mutable
reference to the internal state and the second element of this sequence.
The closure can assign to the internal state to share state between
iterations.
On iteration, the closure will be applied to each element of this
sequence, and the return value from the closure, an Option, is
returned by the next method. The closure can return
Some(value) to yield value, or None to end the iteration.
This is a consuming variant of scan().
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let mut scan = a.scan(1, |state, x| {
// in each iteration, we'll multiply the state by the element ...
*state = *state * x;
// ... and terminate if the state exceeds 6
if *state > 2 {
return None;
}
// ... else yield the negation of the state
Some(-*state)
});
assert_eq!(scan, vec![-1, -2]);Sourcefn scan_ref<S, B>(
&self,
initial_state: S,
function: impl FnMut(&mut S, &Item) -> Option<B>,
) -> Self::This<B>where
Self::This<B>: FromIterator<B>,
fn scan_ref<S, B>(
&self,
initial_state: S,
function: impl FnMut(&mut S, &Item) -> Option<B>,
) -> Self::This<B>where
Self::This<B>: FromIterator<B>,
A sequence adapter which, like fold_ref(), holds an internal state, but
unlike fold_ref(), produces a new sequence.
scan_ref() takes two arguments: an initial value which seeds the internal
state, and a closure with two arguments, the first being a mutable
reference to the internal state and the second element of this sequence.
The closure can assign to the internal state to share state between
iterations.
On iteration, the closure will be applied to each element of this
sequence, and the return value from the closure, an Option, is
returned by the next method. The closure can return
Some(value) to yield value, or None to end the iteration.
This is a non-consuming variant of scan().
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let mut scan = a.scan(1, |state, x| {
// in each iteration, we'll multiply the state by the element ...
*state = *state * x;
// ... and terminate if the state exceeds 6
if *state > 2 {
return None;
}
// ... else yield the negation of the state
Some(-*state)
});
assert_eq!(scan, vec![-1, -2]);Sourcefn skip(self, n: usize) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn skip(self, n: usize) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence that skips the first n elements from this sequence.
skip(n) skips elements until n elements are skipped or the end of this
sequence is reached (whichever happens first). After that, all the remaining
elements are yielded. In particular, if this sequence is too short,
then the returned sequence is empty.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.skip(2), vec![3]);
assert_eq!(a.skip(5), vec![]);Sourcefn skip_while(self, predicate: impl FnMut(&Item) -> bool) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn skip_while(self, predicate: impl FnMut(&Item) -> bool) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence without initial elements based on a predicate.
skip_while() takes a closure as an argument. It will call this
closure on each element of this sequence and ignore elements
until it returns false.
After false is returned, skip_while()’s job is over, and the
rest of the elements are yielded.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.skip_while(|&x| x < 3), vec![3]);Sourcefn slice(self, start_index: usize, end_index: usize) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item>,
fn slice(self, start_index: usize, end_index: usize) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
<Self as IntoIterator>::IntoIter: ExactSizeIterator<Item = Item>,
Creates a new sequence by only including elements in the specified range.
If the specified index exceeds this sequence size, no elements are inserted.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.slice(0, 2), vec![1, 2]);
assert_eq!(a.slice(1, 3), vec![2, 3]);
assert_eq!(a.slice(1, 1), vec![]);Sourcefn sorted(self) -> Self
fn sorted(self) -> Self
Creates a new sequence by sorting this sequence.
This sort is stable (i.e., does not reorder equal elements) and O(n * log(n)) worst-case.
When applicable, unstable sorting is preferred because it is generally faster than stable
sorting, and it doesn’t allocate auxiliary memory.
See sorted_unstable().
§Current implementation
The current algorithm is an adaptive, iterative merge sort inspired by timsort. It is designed to be very fast in cases where this sequence is nearly sorted, or consists of two or more sorted sequences concatenated one after another.
Also, it allocates temporary storage half the size of self, but for short sequences a
non-allocating insertion sort is used instead.
§Examples
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted(), vec![1, 2, 3]);Sourcefn sorted_by(self, compare: impl FnMut(&Item, &Item) -> Ordering) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn sorted_by(self, compare: impl FnMut(&Item, &Item) -> Ordering) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by sorting this sequence with a comparator function.
This sort is stable (i.e., does not reorder equal elements) and O(n * log(n)) worst-case.
The comparator function must define a total ordering for the elements in this sequence. If
the ordering is not total, the order of the elements is unspecified. An order is a
total order if it is (for all a, b and c):
- total and antisymmetric: exactly one of
a < b,a == bora > bis true, and - transitive,
a < bandb < cimpliesa < c. The same must hold for both==and>.
For example, while f64 doesn’t implement Ord because NaN != NaN, we can use
partial_cmp as our sort function when we know this sequence doesn’t contain a NaN.
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted_by(|a, b| a.partial_cmp(b).unwrap()), vec![1, 2, 3]);When applicable, unstable sorting is preferred because it is generally faster than stable
sorting, and it doesn’t allocate auxiliary memory.
See sorted_unstable_by().
§Current implementation
The current algorithm is an adaptive, iterative merge sort inspired by timsort. It is designed to be very fast in cases where this sequence is nearly sorted, or consists of two or more sorted sequences concatenated one after another.
Also, it allocates temporary storage half the size of self, but for short sequences a
non-allocating insertion sort is used instead.
§Example
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted_by(|a, b| a.cmp(b)), vec![1, 2, 3]);Sourcefn sorted_by_cached_key<K: Ord>(self, to_key: impl FnMut(&Item) -> K) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn sorted_by_cached_key<K: Ord>(self, to_key: impl FnMut(&Item) -> K) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by sorting this sequence with a key extraction function.
During sorting, the key function is called at most once per element, by using temporary storage to remember the results of key evaluation. The order of calls to the key function is unspecified and may change in future versions of the standard library.
This sort is stable (i.e., does not reorder equal elements), and O(m * n + n * log(n)) worst-case, where the key function is O(m).
For simple key functions (e.g., functions that are property accesses or
basic operations), sorted_by_key() is likely to be
faster.
§Current implementation
The current algorithm is based on pattern-defeating quicksort by Orson Peters, which combines the fast average case of randomized quicksort with the fast worst case of heapsort, while achieving linear time on sequences with certain patterns. It uses some randomization to avoid degenerate cases, but with a fixed seed to always provide deterministic behavior.
In the worst case, the algorithm allocates temporary storage in a Vec<(K, usize)> the
length of this sequence.
§Example
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted_by_cached_key(|k| k.to_string()), vec![1, 2, 3]);Sourcefn sorted_by_key<K: Ord>(self, to_key: impl FnMut(&Item) -> K) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn sorted_by_key<K: Ord>(self, to_key: impl FnMut(&Item) -> K) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by sorting this sequence with a key extraction function.
This sort is stable (i.e., does not reorder equal elements) and O(m * n * log(n)) worst-case, where the key function is O(m).
For expensive key functions (e.g., functions that are not simple property accesses or
basic operations), sorted_by_cached_key() is likely to be
significantly faster, as it does not recompute element keys.
When applicable, unstable sorting is preferred because it is generally faster than stable
sorting, and it doesn’t allocate auxiliary memory.
See sorted_unstable_by_key().
§Current implementation
The current algorithm is an adaptive, iterative merge sort inspired by timsort. It is designed to be very fast in cases where this sequence is nearly sorted, or consists of two or more sorted sequences concatenated one after another.
Also, it allocates temporary storage half the size of self, but for short sequences a
non-allocating insertion sort is used instead.
§Example
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted_by_key(|&k| -k), vec![3, 2, 1]);Sourcefn sorted_unstable(self) -> Self
fn sorted_unstable(self) -> Self
Creates a new sequence by sorting this sequence, but might not preserve the order of equal elements.
This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not allocate), and O(n * log(n)) worst-case.
§Current implementation
The current algorithm is based on pattern-defeating quicksort by Orson Peters, which combines the fast average case of randomized quicksort with the fast worst case of heapsort, while achieving linear time on sequences with certain patterns. It uses some randomization to avoid degenerate cases, but with a fixed seed to always provide deterministic behavior.
It is typically faster than stable sorting, except in a few special cases, e.g., when this sequence consists of several concatenated sorted sequences.
§Example
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted_unstable(), vec![1, 2, 3]);Sourcefn sorted_unstable_by(
self,
compare: impl FnMut(&Item, &Item) -> Ordering,
) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn sorted_unstable_by(
self,
compare: impl FnMut(&Item, &Item) -> Ordering,
) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by sorting this sequence with a comparator function, but might not preserve the order of equal elements.
This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not allocate), and O(n * log(n)) worst-case.
The comparator function must define a total ordering for the elements in this sequence. If
the ordering is not total, the order of the elements is unspecified. An order is a
total order if it is (for all a, b and c):
- total and antisymmetric: exactly one of
a < b,a == bora > bis true, and - transitive,
a < bandb < cimpliesa < c. The same must hold for both==and>.
For example, while f64 doesn’t implement Ord because NaN != NaN, we can use
partial_cmp as our sort function when we know this sequence doesn’t contain a NaN.
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted_unstable_by(|a, b| a.partial_cmp(b).unwrap()), vec![1, 2, 3]);§Current implementation
The current algorithm is based on pattern-defeating quicksort by Orson Peters, which combines the fast average case of randomized quicksort with the fast worst case of heapsort, while achieving linear time on sequences with certain patterns. It uses some randomization to avoid degenerate cases, but with a fixed seed to always provide deterministic behavior.
It is typically faster than stable sorting, except in a few special cases, e.g., when this sequence consists of several concatenated sorted sequences.
§Example
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted_unstable_by(|a, b| a.cmp(b)), vec![1, 2, 3]);Sourcefn sorted_unstable_by_key<K: Ord>(self, to_key: impl FnMut(&Item) -> K) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn sorted_unstable_by_key<K: Ord>(self, to_key: impl FnMut(&Item) -> K) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence by sorting this sequence with a key extraction function, but might not preserve the order of equal elements.
This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not allocate), and O(m * n * log(n)) worst-case, where the key function is O(m).
§Current implementation
The current algorithm is based on pattern-defeating quicksort by Orson Peters, which combines the fast average case of randomized quicksort with the fast worst case of heapsort, while achieving linear time on slices with certain patterns. It uses some randomization to avoid degenerate cases, but with a fixed seed to always provide deterministic behavior.
Due to its key calling strategy, sorted_unstable_by_key()
is likely to be slower than sorted_by_cached_key() in
cases where the key function is expensive.
§Examples
use cantrip::*;
let a = vec![2, 3, 1];
assert_eq!(a.sorted_unstable_by_key(|&k| -k), vec![3, 2, 1]);Sourcefn step_by(self, step: usize) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn step_by(self, step: usize) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence from this sequence stepping by the given amount for each retained element.
Note: The first element of this sequence will always be returned, regardless of the step given.
§Panics
The method will panic if the given step is 0.
§Examples
use cantrip::*;
let a = vec![1, 2, 2, 3];
assert_eq!(a.step_by(3), vec![1, 3]);
assert_eq!(a.step_by(2), vec![1, 2]);
assert_eq!(a.step_by(1), vec![1, 2, 2, 3]);Sourcefn take(self, n: usize) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn take(self, n: usize) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence that yields the first n elements, or fewer
if this sequence has fewer than n elements.
take(n) yields elements until n elements are yielded or the end of
this sequence is reached (whichever happens first).
The returned sequence is a prefix of length n if this sequence
contains at least n elements, otherwise it contains all the
(fewer than n) elements of this sequence.
§Examples
Basic usage:
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.take(2), vec![1, 2]);If less than n elements are available,
take will limit itself to the size of this sequence:
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.take(2), vec![1, 2]);
assert_eq!(a.take(5), vec![1, 2, 3]);Sourcefn take_while(self, predicate: impl FnMut(&Item) -> bool) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
fn take_while(self, predicate: impl FnMut(&Item) -> bool) -> Selfwhere
Self: IntoIterator<Item = Item> + FromIterator<Item>,
Creates a new sequence without trailing elements based on a predicate.
take_while() takes a closure as an argument. It will call this
closure on each element of this sequence and yield elements
while it returns true.
After false is returned, take_while()’s job is over, and the
rest of the elements are ignored.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.take_while(|&x| x < 3), vec![1, 2]);Sourcefn unique(self) -> Self
fn unique(self) -> Self
Creates a new sequence by omitting duplicate elements.
Duplicates are detected using hash and equality.
The algorithm is stable, returning the non-duplicate items in the order in which they occur in this sequence. In a set of duplicate items, the first item encountered is the item retained.
use cantrip::*;
let a = vec![1, 2, 2, 3];
assert_eq!(a.unique(), vec![1, 2, 3]);Sourcefn unique_by<K>(self, to_key: impl FnMut(&Item) -> K) -> Self
fn unique_by<K>(self, to_key: impl FnMut(&Item) -> K) -> Self
Creates a new sequence by omitting duplicate elements.
Duplicates are detected by comparing the key they map to
with the result of the keying function to_key using hash and equality.
The algorithm is stable, returning the non-duplicate items in the order in which they occur in this sequence. In a set of duplicate items, the first item encountered is the item retained.
use cantrip::*;
let a = vec![1, 2, 2, 3];
assert_eq!(a.unique_by(|x| x % 2), vec![1, 2]);Sourcefn unzip<A, B>(self) -> (Self::This<A>, Self::This<B>)
fn unzip<A, B>(self) -> (Self::This<A>, Self::This<B>)
Creates two new sequences by splitting this sequence of pairs.
unzip() produces two sequences: one from the left elements of the pairs,
and one from the right elements.
This function is, in some sense, the opposite of zip().
§Example
use cantrip::*;
let a = vec![(1, 1), (2, 2), (3, 3)];
let (left, right) = a.unzip();
assert_eq!(left, vec![1, 2, 3]);
assert_eq!(right, vec![1, 2, 3]);Sourcefn variations(&self, k: usize) -> Vec<Self>
fn variations(&self, k: usize) -> Vec<Self>
Creates a new sequence containing variations of specified size from the elements of this sequence.
Specifying size is equal to the length of this sequence produces all permutations of this sequence.
Variations are generated based on element positions, not values.
Therefore, if this sequence contains duplicate elements, the resulting variations will too.
To obtain variations of unique elements, use unique().variations().
The order or variation values is preserved.
§Example
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.variations(0), vec![vec![]]);
assert_eq!(a.variations(1), vec![vec![1], vec![2], vec![3]]);
assert_eq!(a.variations(2), vec![
vec![1, 2],
vec![1, 3],
vec![2, 1],
vec![2, 3],
vec![3, 1],
vec![3, 2]
]);
// Permutations
assert_eq!(a.variations(3), vec![
vec![1, 2, 3],
vec![1, 3, 2],
vec![2, 1, 3],
vec![2, 3, 1],
vec![3, 1, 2],
vec![3, 2, 1],
]);
assert_eq!(e.variations(1), Vec::<Vec<i32>>::new());Sourcefn windowed(&self, size: usize, step: usize) -> Vec<Self>
fn windowed(&self, size: usize, step: usize) -> Vec<Self>
Creates a new sequence consisting of overlapping N element windows
of this sequence, starting at the beginning of this sequence.
The step parameter determines the distance between the first elements of successive windows.
If N is greater than the size of this sequence, it will return no windows.
This is the generalized equivalent of windows().
§Panics
Panics if N is 0. This check will most probably get changed to a compile time
error before this method gets stabilized.
§Examples
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.windowed(2, 1), vec![vec![1, 2], vec![2, 3]]);
assert_eq!(a.windowed(2, 2), vec![vec![1, 2]]);
assert_eq!(e.windowed(1, 1), Vec::<Vec<i32>>::new());Sourcefn windowed_circular(&self, size: usize, step: usize) -> Vec<Self>
fn windowed_circular(&self, size: usize, step: usize) -> Vec<Self>
Creates a new sequence consisting of overlapping N element windows
of this sequence, starting at the beginning of this sequence and wrapping
back to the first elements when the window would otherwise exceed this sequence length.
The step parameter determines the distance between the first elements of successive windows.
If N is greater than the size of this sequence, it will return no windows.
§Panics
Panics if N is 0. This check will most probably get changed to a compile time
error before this method gets stabilized.
§Examples
use cantrip::*;
let a = vec![1, 2, 3];
let e = Vec::<i32>::new();
assert_eq!(a.windowed_circular(2, 1), vec![vec![1, 2], vec![2, 3], vec![3, 1]]);
assert_eq!(a.windowed_circular(2, 2), vec![vec![1, 2], vec![3, 1]]);
assert_eq!(e.windowed_circular(1, 1), Vec::<Vec<i32>>::new());Sourcefn zip<T>(self, elements: impl IntoIterator<Item = T>) -> Self::This<(Item, T)>
fn zip<T>(self, elements: impl IntoIterator<Item = T>) -> Self::This<(Item, T)>
‘Zips up’ this sequence with another collection into a single sequence of pairs.
zip() returns a new sequence containing pairs where the first element comes from
this sequence, and the second element comes from the other collection.
If any of the sequences contains more elements than the other one, the remaining elements are omitted and the resulting sequence length is the length of the shorter sequence.
To ‘undo’ the result of zipping up two sequences, see unzip().
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.zip(vec![4, 5, 6]), vec![(1, 4), (2, 5), (3, 6)]);
assert_eq!(a.zip(vec![4, 5, 6, 7]), vec![(1, 4), (2, 5), (3, 6)]);
assert_eq!(a.zip(vec![4, 5]), vec![(1, 4), (2, 5)]);Sourcefn zip_padded<T>(
self,
elements: impl IntoIterator<Item = T>,
to_left_value: impl FnMut() -> Item,
to_right_value: impl FnMut() -> T,
) -> Self::This<(Item, T)>
fn zip_padded<T>( self, elements: impl IntoIterator<Item = T>, to_left_value: impl FnMut() -> Item, to_right_value: impl FnMut() -> T, ) -> Self::This<(Item, T)>
‘Zips up’ this sequence with another collection into a single sequence of pairs.
zip() returns a new sequence containing pairs where the first element comes from
this sequence, and the second element comes from the other collection.
If this sequence contains fewer elements than the other one, additional elements
are created by calling the to_left_value closure, and the resulting sequence length
is the length of the other sequence.
If this sequence contains more elements than the other one, additional elements
are created by calling the to_right_value closure, and the resulting sequence length
is the length of this sequence.
To ‘undo’ the result of zipping up two sequences, see unzip().
§Example
use cantrip::*;
let a = vec![1, 2, 3];
assert_eq!(a.zip_padded(vec![4, 5, 6], || 1, || 2), vec![(1, 4), (2, 5), (3, 6)],);
assert_eq!(a.zip_padded(vec![4, 5, 6, 7], || 1, || 2), vec![(1, 4), (2, 5), (3, 6), (1, 7)],);
assert_eq!(a.zip_padded(vec![4, 5], || 1, || 2), vec![(1, 4), (2, 5), (3, 2)],);Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.