How to randomly take out an element and delete it from Vec

use rand::prelude::*;

fn main() {
    let mut raw = vec![1, 2, 2, 3, 3, 3, 4];
    let out = choose(raw)
}

fn choose(raw: &mut [u8]) -> u8{
    let out = raw.choose(&mut thread_rng()).unwrap()
    // then how to delete element?
    return out
}

If you want to change the number of items, you need to pass &mut Vec<u8> to the function instead of &mut [u8], which has a fixed length. For example:


use rand::prelude::*;

fn main() {
    let mut raw = vec![1, 2, 2, 3, 3, 3, 4];
    let out = choose(&mut raw);

    dbg!(out, raw);
}

fn choose(raw: &mut Vec<u8>) -> u8{
    let (i, &out) = raw.iter()
                       .enumerate()
                       .choose(&mut thread_rng())
                       .unwrap();
    raw.remove(i);
    out
}

(Playground)

Since you are removing a random element of your vector: if the order of elements in the vector is not important consider using swap_remove as that should be much faster.

1 Like

Applying that advice along with some other refinements (like not panicing on an empty Vec) gives this version:

fn choose(raw: &mut Vec<u8>) -> Option<u8> {
    let i = (0..raw.len()).choose(&mut thread_rng())?;
    Some(raw.swap_remove(i))
}

(Playground)

7 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.