Skip to content

Commit 20773f3

Browse files
committed
Add vec::swap_remove (#3219)
1 parent 4ef1d9d commit 20773f3

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

src/libcore/vec.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ fn consume_mut<T>(+v: ~[mut T], f: fn(uint, +T)) unsafe {
510510
/// Remove the last element from a vector and return it
511511
fn pop<T>(&v: ~[const T]) -> T {
512512
let ln = len(v);
513-
assert ln > 0u;
513+
if ln == 0 {
514+
fail ~"sorry, cannot vec::pop an empty vector"
515+
}
514516
let valptr = ptr::mut_addr_of(v[ln - 1u]);
515517
unsafe {
516518
let val <- *valptr;
@@ -519,6 +521,29 @@ fn pop<T>(&v: ~[const T]) -> T {
519521
}
520522
}
521523

524+
/**
525+
* Remove an element from anywhere in the vector and return it, replacing it
526+
* with the last element. This does not preserve ordering, but is O(1).
527+
*
528+
* Fails if index >= length.
529+
*/
530+
fn swap_remove<T>(&v: ~[const T], index: uint) -> T {
531+
let ln = len(v);
532+
if index >= ln {
533+
fail #fmt("vec::swap_remove - index %u >= length %u", index, ln);
534+
}
535+
let lastptr = ptr::mut_addr_of(v[ln - 1]);
536+
unsafe {
537+
let mut val <- *lastptr;
538+
if index < ln - 1 {
539+
let valptr = ptr::mut_addr_of(v[index]);
540+
*valptr <-> val;
541+
}
542+
unsafe::set_len(v, ln - 1);
543+
val
544+
}
545+
}
546+
522547
/// Append an element to a vector
523548
#[inline(always)]
524549
fn push<T>(&v: ~[const T], +initval: T) {
@@ -1935,6 +1960,34 @@ mod tests {
19351960
assert (e == 5);
19361961
}
19371962

1963+
#[test]
1964+
fn test_swap_remove() {
1965+
let mut v = ~[1, 2, 3, 4, 5];
1966+
let mut e = swap_remove(v, 0);
1967+
assert (len(v) == 4);
1968+
assert e == 1;
1969+
assert (v[0] == 5);
1970+
e = swap_remove(v, 3);
1971+
assert (len(v) == 3);
1972+
assert e == 4;
1973+
assert (v[0] == 5);
1974+
assert (v[1] == 2);
1975+
assert (v[2] == 3);
1976+
}
1977+
1978+
#[test]
1979+
fn test_swap_remove_noncopyable() {
1980+
// Tests that we don't accidentally run destructors twice.
1981+
let mut v = ~[::unsafe::exclusive(()), ::unsafe::exclusive(()),
1982+
::unsafe::exclusive(())];
1983+
let mut _e = swap_remove(v, 0);
1984+
assert (len(v) == 2);
1985+
_e = swap_remove(v, 1);
1986+
assert (len(v) == 1);
1987+
_e = swap_remove(v, 0);
1988+
assert (len(v) == 0);
1989+
}
1990+
19381991
#[test]
19391992
fn test_push() {
19401993
// Test on-stack push().

0 commit comments

Comments
 (0)