为什么对向量调用过滤器不会从向量中删除元素



我正在编写一个小程序,可以找到马拉松的获胜者。一切似乎都是合乎逻辑的,直到我尝试过滤迟到一段时间的跑步者的向量。在过滤器函数之后,向量保持不变,如果使用iter_mut()则说明类型错误。

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);
}

请注意,filter对迭代器进行操作,而不是在向量上运行;它从迭代器中删除元素,而不是从向量中删除元素。执行所需操作的一种方法是将filter的结果收集到新向量中并用它替换旧向量:v = v.iter().filter(whatever).collect();但这将为新向量分配空间,将元素从旧向量复制到新向量中,然后释放旧向量。

有一个实验性 API, drain_filter ,它允许您修改向量并就地删除匹配的元素。但是,由于它是实验性的,因此此 API 暂时仅在夜间可用。

如果你想保持稳定的 Rust 并避免 collect 的开销,你需要手动删除元素。像这样的事情应该这样做(取自drain_filter文档(:

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;
    }
}

迭代器不会更改原始数据结构中的项数。相反,您希望使用retain

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

最新更新