Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to find an element in a Vec<T> and remove it?

Tags:

vector

rust

In Rust, is there an in built function for finding and removing elements of a vector, both simultaneously and as separate actions?

For example:

for f in factors {
    if f in list {
        list.remove(f);
    }
}

Currently, the rust documentation is still a tad confusing, so while my search as shown up nothing, I feel like there is a good chance someone else may have found it.

like image 789
NecroTechno Avatar asked Jun 05 '15 07:06

NecroTechno


People also ask

How do you remove a VEC element?

clear() removes all the elements from a vector container, thus making its size 0. All the elements of the vector are removed using clear() function.

How do you remove an element from a vector in Rust?

To remove all elements from a vector in Rust, use . retain() method to keep all elements the do not match. let mut v = vec![ "A", "warm", "fall", "warm", "day"]; let elem = "warm"; // element to remove v.


3 Answers

The example can be written as:

let mut list = (0..10).collect::<Vec<u32>>();
list.retain(|element| element % 2 == 0);
assert_eq!(&list[..], &[0, 2, 4, 6, 8]);

The relevant documentation can be found here: https://doc.rust-lang.org/std/vec/struct.Vec.html

like image 189
A.B. Avatar answered Oct 08 '22 17:10

A.B.


You could always use an into_iter() to destructure the Vec into an iterator, filter(..) that for the element and collect() into a new Vec:

list.into_iter().filter(|e| !factors.contains(e)).collect();

You may need to specify the type of collect (which should be Vec<T> where T is the type of your element) unless you bind it into a variable of the right type.

Edit: Following A.B.'s advice, you could also write

list.retain(|e| !factors.contains(e))

Note that both would be within O(L × F) where L is the len of list and F the len of factors. For small L and/or F, this will be fine. Otherwise it may be better to convert factors into a HashSet first.

like image 39
llogiq Avatar answered Oct 08 '22 16:10

llogiq


There is no simultaneous "find and remove" method, that I know of. Vec has:

  • remove is the general method to remove an element and shift all the ones that follow to fill the gap
  • swap_remove remove this element and replace it with the last (avoids all the shifting, so it's generally quicker)
  • pop removes the last element (very efficient, might not be what you need if you want to remove an element in the middle of the Vec)

you could do something like:

let mut v = vec![1, 2, 3];
// iterate through the vector and return the position for the
// first element == 2. If something is found bind it to the name
// index
if let Some(index) = v.iter().position(|&i| i == 2) {
    v.remove(index); // remove the element at the position index (2)
}

println!("{:?}", v); // prints [1, 3]
like image 3
Paolo Falabella Avatar answered Oct 08 '22 18:10

Paolo Falabella