Skip to content

Implement append and split_off for VecMap (RFC 509) #22494

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 23, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 170 additions & 2 deletions src/libcollections/vec_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ use self::Entry::*;

use core::prelude::*;

use core::cmp::Ordering;
use core::cmp::{max, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{Hash, Hasher};
#[cfg(stage0)] use core::hash::Writer;
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
use core::iter;
use core::mem::replace;
use core::mem::{replace, swap};
use core::ops::{Index, IndexMut};

use {vec, slice};
Expand Down Expand Up @@ -335,6 +335,95 @@ impl<V> VecMap<V> {
IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) }
}

/// Moves all elements from `other` into the map while overwriting existing keys.
///
/// # Examples
///
/// ```
/// use std::collections::VecMap;
///
/// let mut a = VecMap::new();
/// a.insert(1, "a");
/// a.insert(2, "b");
///
/// let mut b = VecMap::new();
/// b.insert(3, "c");
/// b.insert(4, "d");
///
/// a.append(&mut b);
///
/// assert_eq!(a.len(), 4);
/// assert_eq!(b.len(), 0);
/// assert_eq!(a[1], "a");
/// assert_eq!(a[2], "b");
/// assert_eq!(a[3], "c");
/// assert_eq!(a[4], "d");
/// ```
#[unstable(feature = "collections",
reason = "recently added as part of collections reform 2")]
pub fn append(&mut self, other: &mut Self) {
self.extend(other.drain());
}

/// Splits the collection into two at the given key.
///
/// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
/// and the returned `Self` contains elements `[at, max_key)`.
///
/// Note that the capacity of `self` does not change.
///
/// # Examples
///
/// ```
/// use std::collections::VecMap;
///
/// let mut a = VecMap::new();
/// a.insert(1, "a");
/// a.insert(2, "b");
/// a.insert(3, "c");
/// a.insert(4, "d");
///
/// let b = a.split_off(3);
///
/// assert_eq!(a[1], "a");
/// assert_eq!(a[2], "b");
///
/// assert_eq!(b[3], "c");
/// assert_eq!(b[4], "d");
/// ```
#[unstable(feature = "collections",
reason = "recently added as part of collections reform 2")]
pub fn split_off(&mut self, at: usize) -> Self {
let mut other = VecMap::new();

if at == 0 {
// Move all elements to other
swap(self, &mut other);
return other
} else if at > self.v.len() {
// No elements to copy
return other;
}

// Look up the index of the first non-None item
let first_index = self.v.iter().position(|el| el.is_some());
let start_index = match first_index {
Some(index) => max(at, index),
None => {
// self has no elements
return other;
}
};

// Fill the new VecMap with `None`s until `start_index`
other.v.extend((0..start_index).map(|_| None));

// Move elements beginning with `start_index` from `self` into `other`
other.v.extend(self.v[start_index..].iter_mut().map(|el| el.take()));

other
}

/// Returns an iterator visiting all key-value pairs in ascending order of
/// the keys, emptying (but not consuming) the original `VecMap`.
/// The iterator's element type is `(usize, &'r V)`. Keeps the allocated memory for reuse.
Expand Down Expand Up @@ -1156,6 +1245,85 @@ mod test_map {
assert_eq!(map.len(), 0);
}

#[test]
fn test_append() {
let mut a = VecMap::new();
a.insert(1, "a");
a.insert(2, "b");
a.insert(3, "c");

let mut b = VecMap::new();
b.insert(3, "d"); // Overwrite element from a
b.insert(4, "e");
b.insert(5, "f");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, you can collect an iterator of tuples. e.g. [(1, "a"), (2, "b"), (3, "c")].


a.append(&mut b);

assert_eq!(a.len(), 5);
assert_eq!(b.len(), 0);
// Capacity shouldn't change for possible reuse
assert!(b.capacity() >= 4);

assert_eq!(a[1], "a");
assert_eq!(a[2], "b");
assert_eq!(a[3], "d");
assert_eq!(a[4], "e");
assert_eq!(a[5], "f");
}

#[test]
fn test_split_off() {
// Split within the key range
let mut a = VecMap::new();
a.insert(1, "a");
a.insert(2, "b");
a.insert(3, "c");
a.insert(4, "d");

let b = a.split_off(3);

assert_eq!(a.len(), 2);
assert_eq!(b.len(), 2);

assert_eq!(a[1], "a");
assert_eq!(a[2], "b");

assert_eq!(b[3], "c");
assert_eq!(b[4], "d");

// Split at 0
a.clear();
a.insert(1, "a");
a.insert(2, "b");
a.insert(3, "c");
a.insert(4, "d");

let b = a.split_off(0);

assert_eq!(a.len(), 0);
assert_eq!(b.len(), 4);
assert_eq!(b[1], "a");
assert_eq!(b[2], "b");
assert_eq!(b[3], "c");
assert_eq!(b[4], "d");

// Split behind max_key
a.clear();
a.insert(1, "a");
a.insert(2, "b");
a.insert(3, "c");
a.insert(4, "d");

let b = a.split_off(5);

assert_eq!(a.len(), 4);
assert_eq!(b.len(), 0);
assert_eq!(a[1], "a");
assert_eq!(a[2], "b");
assert_eq!(a[3], "c");
assert_eq!(a[4], "d");
}

#[test]
fn test_show() {
let mut map = VecMap::new();
Expand Down