Why does calling filter on a vector not remove elements from the vector?

只愿长相守 提交于 2019-12-24 19:13:13

问题


I am writing a small program that finds a winner of a marathon. Everything seems logical until I try to filter the vector for runners that are late for some amount of time. The vector remains same after the filter function, and if use iter_mut() it states type errors.

fn main() {
    let mut input_line = String::new();
    std::io::stdin().read_line(&mut input_line);
    let n = input_line.trim().parse::<u8>().unwrap();
    let mut v = Vec::with_capacity(n as usize);
    for _ in 0..n {
        let mut input_line = String::new();
        std::io::stdin().read_line(&mut input_line);
        let separated = input_line.trim().split(":").collect::<Vec<_>>();
        let hours = separated[0].parse::<u8>().unwrap();
        let minutes = separated[1].parse::<u8>().unwrap();
        let seconds = separated[2].parse::<u8>().unwrap();
        v.push((hours, minutes, seconds));
    }

    //println!("{:?}", v);
    filter_hours(&mut v);
    filter_minutes(&mut v);
    filter_seconds(&mut v);
    println!("{:?}", v[0]);

    println!("{:?}", v);
}

fn filter_hours(v: &mut Vec<(u8, u8, u8)>) {
    let (mut minimum, _, _) = v[0];
    for &i in v.iter() {
        let (h, _, _) = i;
        if h < minimum {
            minimum = h;
        }
    }
    v.iter().filter(|&&(h, _, _)| h == minimum);
}

fn filter_minutes(v: &mut Vec<(u8, u8, u8)>) {
    let (_, mut minimum, _) = v[0];
    for &i in v.iter() {
        let (_, m, _) = i;
        if m < minimum {
            minimum = m;
        }
    }
    v.iter().filter(|&&(_, m, _)| m == minimum);
}

fn filter_seconds(v: &mut Vec<(u8, u8, u8)>) {
    let (_, _, mut minimum) = v[0];
    for &i in v.iter() {
        let (_, _, s) = i;
        if s < minimum {
            minimum = s;
        }
    }
    v.iter().filter(|&&(_, _, s)| s == minimum);
}

回答1:


Iterators do not alter the number of items in the original data structure. Instead, you want to use retain:

fn filter_hours(v: &mut Vec<(u8, u8, u8)>) {
    let min = v.iter().map(|&(h, _, _)| h).min().unwrap();
    v.retain(|&(h, _, _)| h == min);
}



回答2:


Note that filter operates on an iterator, not on the vector; it removes elements from the iterator and not from the vector. One way to do what you want is to collect the result of filter into a new vector and replace the old one with it: v = v.iter().filter(whatever).collect(); but this will allocate space for a new vector, copy the elements from the old vector into the new one, then free the old vector.

There is an experimental API, drain_filter, which allows you to modify the vector and remove matching elements in place. However since it is experimental, this API is only available in nightly for the time being.

If you want to keep to stable Rust and avoid the overhead of collect, you will need to remove the elements by hand. Something like this should do it (taken from the drain_filter docs):

let mut i = 0;
while i != vec.len() {
    if some_predicate(&mut vec[i]) {
        let val = vec.remove(i);
        // your code here
    } else {
        i += 1;
    }
}


来源:https://stackoverflow.com/questions/49128666/why-does-calling-filter-on-a-vector-not-remove-elements-from-the-vector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!