Skip to content

Commit

Permalink
Auto merge of #112818 - Benjamin-L:add-slice_split_once, r=cuviper
Browse files Browse the repository at this point in the history
Implement `slice::split_once` and `slice::rsplit_once`

Feature gate is `slice_split_once` and tracking issue is #112811. These are equivalents to the existing `str::split_once` and `str::rsplit_once` methods.
  • Loading branch information
bors committed Oct 10, 2023
2 parents d627cf0 + 50246b0 commit 1b2137f
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 0 deletions.
56 changes: 56 additions & 0 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2482,6 +2482,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*).
Expand Down
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,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)]
Expand Down
20 changes: 20 additions & 0 deletions library/core/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2476,6 +2476,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)*);
Expand Down

0 comments on commit 1b2137f

Please sign in to comment.