代码之家  ›  专栏  ›  技术社区  ›  Nemanja Beric

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

  •  0
  • Nemanja Beric  · 技术社区  · 7 年前

    我正在写一个寻找马拉松冠军的小程序。 在我尝试筛选出迟到一段时间的跑步者之前,一切似乎都是合乎逻辑的。使用过滤器函数后,向量保持不变,如果使用 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);
    }
    
    2 回复  |  直到 7 年前
        1
  •  4
  •   Shepmaster Tim Diekmann    7 年前

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

    有一个实验API, drain_filter ,它允许您修改向量并在适当位置删除匹配元素。然而,由于该API是实验性的,因此目前只能在夜间使用。

    如果你想保持稳定的锈蚀,避免 collect ,则需要手动移除这些元素。像这样的东西应该可以做到(摘自 drain\u过滤器 文档):

    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;
        }
    }
    
        2
  •  3
  •   Shepmaster Tim Diekmann    7 年前

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

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