Implement slice::split_once and slice::rsplit_once

Feature gate is slice_split_once and tracking issue is #112811.
This commit is contained in:
Benjamin Lee 2023-06-19 17:50:14 -07:00
parent c911e08514
commit 50246b0587
No known key found for this signature in database
GPG Key ID: FB9624E2885D55A4
3 changed files with 77 additions and 0 deletions

View File

@ -2478,6 +2478,62 @@ impl<T> [T] {
RSplitNMut::new(self.rsplit_mut(pred), n)
}
/// Splits the slice on the first element that matches the specified
/// predicate.
///
/// If any matching elements are resent in the slice, returns the prefix
/// before the match and suffix after. The matching element itself is not
/// included. If no elements match, returns `None`.
///
/// # Examples
///
/// ```
/// #![feature(slice_split_once)]
/// let s = [1, 2, 3, 2, 4];
/// assert_eq!(s.split_once(|&x| x == 2), Some((
/// &[1][..],
/// &[3, 2, 4][..]
/// )));
/// assert_eq!(s.split_once(|&x| x == 0), None);
/// ```
#[unstable(feature = "slice_split_once", reason = "newly added", issue = "112811")]
#[inline]
pub fn split_once<F>(&self, pred: F) -> Option<(&[T], &[T])>
where
F: FnMut(&T) -> bool,
{
let index = self.iter().position(pred)?;
Some((&self[..index], &self[index + 1..]))
}
/// Splits the slice on the last element that matches the specified
/// predicate.
///
/// If any matching elements are resent in the slice, returns the prefix
/// before the match and suffix after. The matching element itself is not
/// included. If no elements match, returns `None`.
///
/// # Examples
///
/// ```
/// #![feature(slice_split_once)]
/// let s = [1, 2, 3, 2, 4];
/// assert_eq!(s.rsplit_once(|&x| x == 2), Some((
/// &[1, 2, 3][..],
/// &[4][..]
/// )));
/// assert_eq!(s.rsplit_once(|&x| x == 0), None);
/// ```
#[unstable(feature = "slice_split_once", reason = "newly added", issue = "112811")]
#[inline]
pub fn rsplit_once<F>(&self, pred: F) -> Option<(&[T], &[T])>
where
F: FnMut(&T) -> bool,
{
let index = self.iter().rposition(pred)?;
Some((&self[..index], &self[index + 1..]))
}
/// Returns `true` if the slice contains an element with the given value.
///
/// This operation is *O*(*n*).

View File

@ -47,6 +47,7 @@
#![feature(sort_internals)]
#![feature(slice_take)]
#![feature(slice_from_ptr_range)]
#![feature(slice_split_once)]
#![feature(split_as_slice)]
#![feature(maybe_uninit_uninit_array)]
#![feature(maybe_uninit_write_slice)]

View File

@ -2448,6 +2448,26 @@ fn slice_rsplit_array_mut_out_of_bounds() {
let _ = v.rsplit_array_mut::<7>();
}
#[test]
fn slice_split_once() {
let v = &[1, 2, 3, 2, 4][..];
assert_eq!(v.split_once(|&x| x == 2), Some((&[1][..], &[3, 2, 4][..])));
assert_eq!(v.split_once(|&x| x == 1), Some((&[][..], &[2, 3, 2, 4][..])));
assert_eq!(v.split_once(|&x| x == 4), Some((&[1, 2, 3, 2][..], &[][..])));
assert_eq!(v.split_once(|&x| x == 0), None);
}
#[test]
fn slice_rsplit_once() {
let v = &[1, 2, 3, 2, 4][..];
assert_eq!(v.rsplit_once(|&x| x == 2), Some((&[1, 2, 3][..], &[4][..])));
assert_eq!(v.rsplit_once(|&x| x == 1), Some((&[][..], &[2, 3, 2, 4][..])));
assert_eq!(v.rsplit_once(|&x| x == 4), Some((&[1, 2, 3, 2][..], &[][..])));
assert_eq!(v.rsplit_once(|&x| x == 0), None);
}
macro_rules! take_tests {
(slice: &[], $($tts:tt)*) => {
take_tests!(ty: &[()], slice: &[], $($tts)*);