If you know that slice actually fulfills this partitioning, your best bet is to use the double partition_point approach.
fn partition_twice_slice<T>(
vs: &[T],
start_pred: impl Fn(&T) -> bool,
end_pred: impl Fn(&T) -> bool,
) -> &[T] {
let start = vs.partition_point(start_pred);
let end = start + vs[start..].partition_point(end_pred);
&vs[start..end]
}
If you just need the first slice that fulfills the partitioning requirements, you can get more creative.
On iterators you can use skip_while and take_while:
fn partition_twice_iter<T>(
vs: Vec<T>,
start_pred: impl Fn(&T) -> bool,
end_pred: impl Fn(&T) -> bool,
) -> Vec<T> {
vs.into_iter()
.skip_while(|el| start_pred(el))
.take_while(|el| end_pred(el))
.collect()
}
If you only need the slice, you can adapt this to find the bound indices:
fn partition_twice_slice<T>(
vs: &[T],
start_pred: impl Fn(&T) -> bool,
end_pred: impl Fn(&T) -> bool,
) -> &[T] {
let start = (0..vs.len())
.find(|&i| start_pred(&vs[i]))
.unwrap_or(vs.len());
let end = (start..vs.len())
.find(|&i| !end_pred(&vs[i]))
.unwrap_or(vs.len());
&vs[start..end]
}
Example usage:
fn main() {
assert_eq!(
partition_twice_iter(vec![1, 2, 3, 4, 5, 6, 7, 8, 9], |&x| x <= 3, |&x| x < 7),
vec![4, 5, 6]
);
assert_eq!(
partition_twice_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9], |&x| x <= 3, |&x| x < 7),
&[4, 5, 6]
);
}
Note that I turned around your x > 3 requirement to better fit the convention of partition_point.