[Easy] More Rustic syntax for retaining values and indices of Vec

Just wondering if there is a more functional / rustic approach to retaining both indices and values from a vector whose value satisfy a condition.

Working snippet as follows:


fn main() {
    let x = vec![1, 2, 3, 4];
    let mut indices = vec![];
    let mut keepers = vec![];
    for (i, v) in x.iter().enumerate() {
        if v % 2 == 0 {
            keepers.push(v);
            indices.push(i);
        }
    }
    // println!("{:?}-{:?}", indices, keepers);
}

Of course I can easily get the values by making x mutable and using x.retain, but would also like to know which indices have either been kept or lost in the process.

(Playground)

You can use .filter() on the enumerated iterator. Then you can process the filtered iterator as you want (for example collecting it into one or two vectors [collect or unzip], or processing it further).

2 Likes

Why not use a HashMap?

use std::collections::HashMap;
fn main() {
    let x = vec![1, 2, 3, 4];
    let mut my_hashmap = HashMap::new();
    for (i, v) in x.iter().enumerate() {
        if v % 2 == 0 {
            my_hashmap.insert(i.to_string(), v);
        }
    }
    for (k, v) in my_hashmap {
        println!("{}: {}", k,v);
    }
}

How about using Iterator::partition after enumerate?

maybe this:

    let k: HashMap<usize, u32> = x
        .iter()
        .copied()
        .enumerate()
        .filter(|(_, value)| value % 2u32 == 0)
        .collect();

Yes! Something like this for example

let x = vec![1, 2, 3, 4];
let (indices, keepers): (Vec<_>, Vec<_>) = x
    .iter()
    .copied()
    .enumerate()
    .filter(|(i, v)| *v % 2 == 0)
    .unzip();