Skip to content

Instantly share code, notes, and snippets.

@orez-
Last active February 25, 2024 01:51
Show Gist options
  • Save orez-/ff82d2a1646385b302770257f63970bd to your computer and use it in GitHub Desktop.
Save orez-/ff82d2a1646385b302770257f63970bd to your computer and use it in GitHub Desktop.
struct SplitBy<'a, T> {
slice: &'a [T],
value: T,
last_idx: usize,
}
impl<'a, T: PartialEq> Iterator for SplitBy<'a, T> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
if self.last_idx >= self.slice.len() { return None; }
let start = self.last_idx;
self.last_idx = self.slice[self.last_idx..].iter()
.position(|p| p == &self.value)
.map_or_else(|| self.slice.len(), |offset| offset + self.last_idx) + 1;
Some(&self.slice[start..self.last_idx - 1])
}
}
fn split_by<T>(slice: &[T], value: T) -> SplitBy<T> {
SplitBy { slice, value, last_idx: 0 }
}
struct SplitWhen<'a, T, F> {
slice: &'a [T],
f: F,
}
impl<'a, T, F> Iterator for SplitWhen<'a, T, F>
where F: FnMut(&T, &T) -> bool {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
if self.slice.is_empty() {
return None;
}
let idx = self.slice
.windows(2)
.position(|w| (self.f)(&w[0], &w[1]))
.unwrap_or(self.slice.len() - 1);
let (start, end) = self.slice.split_at(idx + 1);
self.slice = end;
Some(start)
}
}
fn split_when<T, F>(slice: &[T], mut f: F) -> SplitWhen<'_, T, F>
where F: FnMut(&T, &T) -> bool
{
SplitWhen { slice, f }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment