Auto merge of #71780 - jcotton42:string_remove_matches, r=joshtriplett
Implement String::remove_matches Closes #50206. I lifted the function help from `@frewsxcv's` original PR (#50015), hope they don't mind. I'm also wondering whether it would be useful for `remove_matches` to collect up the removed substrings into a `Vec` and return them, right now they're just overwritten by the copy and lost.
This commit is contained in:
commit
eb95acea8a
@ -1202,6 +1202,62 @@ impl String {
|
||||
ch
|
||||
}
|
||||
|
||||
/// Remove all matches of pattern `pat` in the `String`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(string_remove_matches)]
|
||||
/// let mut s = String::from("Trees are not green, the sky is not blue.");
|
||||
/// s.remove_matches("not ");
|
||||
/// assert_eq!("Trees are green, the sky is blue.", s);
|
||||
/// ```
|
||||
///
|
||||
/// Matches will be detected and removed iteratively, so in cases where
|
||||
/// patterns overlap, only the first pattern will be removed:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(string_remove_matches)]
|
||||
/// let mut s = String::from("banana");
|
||||
/// s.remove_matches("ana");
|
||||
/// assert_eq!("bna", s);
|
||||
/// ```
|
||||
#[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")]
|
||||
pub fn remove_matches<'a, P>(&'a mut self, pat: P)
|
||||
where
|
||||
P: for<'x> Pattern<'x>,
|
||||
{
|
||||
use core::str::pattern::Searcher;
|
||||
|
||||
let matches = {
|
||||
let mut searcher = pat.into_searcher(self);
|
||||
let mut matches = Vec::new();
|
||||
|
||||
while let Some(m) = searcher.next_match() {
|
||||
matches.push(m);
|
||||
}
|
||||
|
||||
matches
|
||||
};
|
||||
|
||||
let len = self.len();
|
||||
let mut shrunk_by = 0;
|
||||
|
||||
// SAFETY: start and end will be on utf8 byte boundaries per
|
||||
// the Searcher docs
|
||||
unsafe {
|
||||
for (start, end) in matches {
|
||||
ptr::copy(
|
||||
self.vec.as_mut_ptr().add(end - shrunk_by),
|
||||
self.vec.as_mut_ptr().add(start - shrunk_by),
|
||||
len - end,
|
||||
);
|
||||
shrunk_by += end - start;
|
||||
}
|
||||
self.vec.set_len(len - shrunk_by);
|
||||
}
|
||||
}
|
||||
|
||||
/// Retains only the characters specified by the predicate.
|
||||
///
|
||||
/// In other words, remove all characters `c` such that `f(c)` returns `false`.
|
||||
|
@ -22,6 +22,7 @@
|
||||
#![feature(slice_partition_dedup)]
|
||||
#![feature(vec_extend_from_within)]
|
||||
#![feature(vec_spare_capacity)]
|
||||
#![feature(string_remove_matches)]
|
||||
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -365,6 +365,33 @@ fn remove_bad() {
|
||||
"ศ".to_string().remove(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_matches() {
|
||||
let mut s = "abc".to_string();
|
||||
|
||||
s.remove_matches('b');
|
||||
assert_eq!(s, "ac");
|
||||
s.remove_matches('b');
|
||||
assert_eq!(s, "ac");
|
||||
|
||||
let mut s = "abcb".to_string();
|
||||
|
||||
s.remove_matches('b');
|
||||
assert_eq!(s, "ac");
|
||||
|
||||
let mut s = "ศไทย中华Việt Nam; foobarศ".to_string();
|
||||
s.remove_matches('ศ');
|
||||
assert_eq!(s, "ไทย中华Việt Nam; foobar");
|
||||
|
||||
let mut s = "".to_string();
|
||||
s.remove_matches("");
|
||||
assert_eq!(s, "");
|
||||
|
||||
let mut s = "aaaaa".to_string();
|
||||
s.remove_matches('a');
|
||||
assert_eq!(s, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_retain() {
|
||||
let mut s = String::from("α_β_γ");
|
||||
|
Loading…
x
Reference in New Issue
Block a user