Add method String::retain
Behaves like `Vec::retain`, accepting a predicate `FnMut(char) -> bool` and reducing the string to only characters for which the predicate returns `true`.
This commit is contained in:
parent
599be0d18f
commit
618ac89d25
4 changed files with 95 additions and 0 deletions
23
src/doc/unstable-book/src/library-features/string-retain.md
Normal file
23
src/doc/unstable-book/src/library-features/string-retain.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# `string_retain`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#43874]
|
||||||
|
|
||||||
|
[#43874]: https://github.com/rust-lang/rust/issues/43874
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Retains only the characters specified by the predicate.
|
||||||
|
|
||||||
|
In other words, remove all characters `c` such that `f(c)` returns `false`.
|
||||||
|
This method operates in place and preserves the order of the retained
|
||||||
|
characters.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#![feature(string_retain)]
|
||||||
|
|
||||||
|
let mut s = String::from("f_o_ob_ar");
|
||||||
|
|
||||||
|
s.retain(|c| c != '_');
|
||||||
|
|
||||||
|
assert_eq!(s, "foobar");
|
||||||
|
```
|
|
@ -1031,6 +1031,57 @@ impl String {
|
||||||
ch
|
ch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retains only the characters specified by the predicate.
|
||||||
|
///
|
||||||
|
/// In other words, remove all characters `c` such that `f(c)` returns `false`.
|
||||||
|
/// This method operates in place and preserves the order of the retained
|
||||||
|
/// characters.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(string_retain)]
|
||||||
|
///
|
||||||
|
/// let mut s = String::from("f_o_ob_ar");
|
||||||
|
///
|
||||||
|
/// s.retain(|c| c != '_');
|
||||||
|
///
|
||||||
|
/// assert_eq!(s, "foobar");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "string_retain", issue = "43874")]
|
||||||
|
pub fn retain<F>(&mut self, mut f: F)
|
||||||
|
where F: FnMut(char) -> bool
|
||||||
|
{
|
||||||
|
let len = self.len();
|
||||||
|
let mut del_bytes = 0;
|
||||||
|
let mut idx = 0;
|
||||||
|
|
||||||
|
while idx < len {
|
||||||
|
let ch = unsafe {
|
||||||
|
self.slice_unchecked(idx, len).chars().next().unwrap()
|
||||||
|
};
|
||||||
|
let ch_len = ch.len_utf8();
|
||||||
|
|
||||||
|
if !f(ch) {
|
||||||
|
del_bytes += ch_len;
|
||||||
|
} else if del_bytes > 0 {
|
||||||
|
unsafe {
|
||||||
|
ptr::copy(self.vec.as_ptr().offset(idx as isize),
|
||||||
|
self.vec.as_mut_ptr().offset((idx - del_bytes) as isize),
|
||||||
|
ch_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Point idx to the next char
|
||||||
|
idx += ch_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if del_bytes > 0 {
|
||||||
|
unsafe { self.vec.set_len(len - del_bytes); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Inserts a character into this `String` at a byte position.
|
/// Inserts a character into this `String` at a byte position.
|
||||||
///
|
///
|
||||||
/// This is an `O(n)` operation as it requires copying every element in the
|
/// This is an `O(n)` operation as it requires copying every element in the
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#![feature(splice)]
|
#![feature(splice)]
|
||||||
#![feature(str_checked_slicing)]
|
#![feature(str_checked_slicing)]
|
||||||
#![feature(str_escape)]
|
#![feature(str_escape)]
|
||||||
|
#![feature(string_retain)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
|
|
|
@ -332,6 +332,26 @@ fn remove_bad() {
|
||||||
"ศ".to_string().remove(1);
|
"ศ".to_string().remove(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_retain() {
|
||||||
|
let mut s = String::from("α_β_γ");
|
||||||
|
|
||||||
|
s.retain(|_| true);
|
||||||
|
assert_eq!(s, "α_β_γ");
|
||||||
|
|
||||||
|
s.retain(|c| c != '_');
|
||||||
|
assert_eq!(s, "αβγ");
|
||||||
|
|
||||||
|
s.retain(|c| c != 'β');
|
||||||
|
assert_eq!(s, "αγ");
|
||||||
|
|
||||||
|
s.retain(|c| c == 'α');
|
||||||
|
assert_eq!(s, "α");
|
||||||
|
|
||||||
|
s.retain(|_| false);
|
||||||
|
assert_eq!(s, "");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert() {
|
fn insert() {
|
||||||
let mut s = "foobar".to_string();
|
let mut s = "foobar".to_string();
|
||||||
|
|
Loading…
Reference in a new issue