Reputation: 675
Does the standard library provide a way to split a slice [T]
using another slice of the same type as a delimiter? The library's documentation lists methods that operate on single-element delimiters rather than slices.
For example: A slice of 5 u64
integers [1u64, 4u64, 0u64, 0u64, 8u64]
split using [0u64, 0u64]
as a delimiter would result in two slices [1u64, 4u64]
and [8u64]
.
Upvotes: 5
Views: 674
Reputation: 11177
Does the standard library provide a way to split a slice
[T]
using another slice of the same type as a delimiter?
As of Rust 1.9, no, but you can implement it:
fn main() {
let a = [1, 4, 7, 0, 0, 8, 10, 0, 0];
let b = [0, 0];
let mut iter = split_subsequence(&a, &b);
assert_eq!(&[1, 4, 7], iter.next().unwrap());
assert_eq!(&[8, 10], iter.next().unwrap());
assert!(iter.next().unwrap().is_empty());
assert_eq!(None, iter.next());
}
pub struct SplitSubsequence<'a, 'b, T: 'a + 'b> {
slice: &'a [T],
needle: &'b [T],
ended: bool,
}
impl<'a, 'b, T: 'a + 'b + PartialEq> Iterator for SplitSubsequence<'a, 'b, T> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
if self.ended {
None
} else if self.slice.is_empty() {
self.ended = true;
Some(self.slice)
} else if let Some(p) = self.slice
.windows(self.needle.len())
.position(|w| w == self.needle) {
let item = &self.slice[..p];
self.slice = &self.slice[p + self.needle.len()..];
Some(item)
} else {
self.ended = true;
let item = self.slice;
self.slice = &self.slice[self.slice.len() - 1..];
Some(item)
}
}
}
fn split_subsequence<'a, 'b, T>(slice: &'a [T], needle: &'b [T]) -> SplitSubsequence<'a, 'b, T>
where T: 'a + 'b + PartialEq
{
SplitSubsequence {
slice: slice,
needle: needle,
ended: false,
}
}
Note that this implementation uses a naive algorithm for finding an equal subsequence.
Upvotes: 4