Add Vec::dedup_by and Vec::dedup_by_key
This commit is contained in:
parent
f14f4db6e8
commit
be34bac1ab
@ -1156,7 +1156,52 @@ impl<T: PartialEq> Vec<T> {
|
||||
/// assert_eq!(vec, [1, 2, 3, 2]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn dedup(&mut self) {
|
||||
self.dedup_by(|a, b| a == b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Vec<T> {
|
||||
/// Removes consecutive elements in the vector that resolve to the same key.
|
||||
///
|
||||
/// If the vector is sorted, this removes all duplicates.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(dedup_by)]
|
||||
///
|
||||
/// let mut vec = vec![10, 20, 21, 30, 20];
|
||||
///
|
||||
/// vec.dedup_by_key(|i| *i / 10);
|
||||
///
|
||||
/// assert_eq!(vec, [10, 20, 30, 20]);
|
||||
/// ```
|
||||
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
|
||||
#[inline]
|
||||
pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq {
|
||||
self.dedup_by(|a, b| key(a) == key(b))
|
||||
}
|
||||
|
||||
/// Removes consecutive elements in the vector that resolve to the same key.
|
||||
///
|
||||
/// If the vector is sorted, this removes all duplicates.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(dedup_by)]
|
||||
/// use std::ascii::AsciiExt;
|
||||
///
|
||||
/// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
|
||||
///
|
||||
/// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
|
||||
///
|
||||
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
|
||||
/// ```
|
||||
#[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")]
|
||||
pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
|
||||
unsafe {
|
||||
// Although we have a mutable reference to `self`, we cannot make
|
||||
// *arbitrary* changes. The `PartialEq` comparisons could panic, so we
|
||||
@ -1228,7 +1273,7 @@ impl<T: PartialEq> Vec<T> {
|
||||
while r < ln {
|
||||
let p_r = p.offset(r as isize);
|
||||
let p_wm1 = p.offset((w - 1) as isize);
|
||||
if *p_r != *p_wm1 {
|
||||
if !same_bucket(&mut *p_r, &mut *p_wm1) {
|
||||
if r != w {
|
||||
let p_w = p_wm1.offset(1);
|
||||
mem::swap(&mut *p_r, &mut *p_w);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#![feature(collections)]
|
||||
#![feature(collections_bound)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(dedup_by)]
|
||||
#![feature(enumset)]
|
||||
#![feature(pattern)]
|
||||
#![feature(rand)]
|
||||
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::iter::{FromIterator, repeat};
|
||||
use std::mem::size_of;
|
||||
@ -230,6 +231,31 @@ fn test_dedup() {
|
||||
case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dedup_by_key() {
|
||||
fn case(a: Vec<i32>, b: Vec<i32>) {
|
||||
let mut v = a;
|
||||
v.dedup_by_key(|i| *i / 10);
|
||||
assert_eq!(v, b);
|
||||
}
|
||||
case(vec![], vec![]);
|
||||
case(vec![10], vec![10]);
|
||||
case(vec![10, 11], vec![10]);
|
||||
case(vec![10, 20, 30], vec![10, 20, 30]);
|
||||
case(vec![10, 11, 20, 30], vec![10, 20, 30]);
|
||||
case(vec![10, 20, 21, 30], vec![10, 20, 30]);
|
||||
case(vec![10, 20, 30, 31], vec![10, 20, 30]);
|
||||
case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dedup_by() {
|
||||
let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
|
||||
vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
|
||||
|
||||
assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dedup_unique() {
|
||||
let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3];
|
||||
|
Loading…
Reference in New Issue
Block a user