【问题标题】:Comparing every element in a vector with the next one将向量中的每个元素与下一个元素进行比较
【发布时间】:2020-07-03 08:30:17
【问题描述】:

我想将向量的每个元素与下一个元素进行比较。我找到了以下解决方案,但它不是那么可读。

struct Obj {
    i: u32,
}

impl Obj {
    fn is_valid_next(&self, next: &Obj) -> bool {
        self.i + 1 == next.i
    }
}

fn main() {
    let data: Vec<Obj> = vec![Obj { i: 0 }, Obj { i: 2 }, Obj { i: 2 }];
    let mut previous: Option<Obj> = None;
    let mut is_valid = true;
    for current in data.into_iter() {
        match previous {
            Some(p) => {
                is_valid = p.is_valid_next(&current);
                if !is_valid {
                    break;
                }
            }
            None => {}
        }
        previous = Some(current);
    }
    println!("is valid {}", is_valid);
}

【问题讨论】:

    标签: rust


    【解决方案1】:

    这可以通过多种方式完成。

    使用slice::windows

    slice::windows:

    在所有长度大小的连续窗口上返回一个迭代器。

    在这种情况下,窗口大小将为2,因此windows 将返回一个迭代器,该迭代器将屏蔽 2 个元素,并且每次迭代都会向右移动。

    initial position : [|0, 5|, 10, 40, 30] // &[0, 5]
    next position    : [0, |5, 10|, 40, 30] // &[5, 10]
    

    以下是针对您的问题的应用解决方案:

    fn main() {
        let data: Vec<Obj> = vec![Obj { i: 0 }, Obj { i: 1 }, Obj { i: 2 }, Obj { i: 3 }];
    
        let is_valid = data.windows(2).all(|w| w[0].is_valid_next(&w[1]));
    
        println!("Is consecutive -> {:?}", is_valid); // true
    }
    

    Playground

    请注意,切片的直接索引访问可能会导致 panic,但由于从 Windows 迭代器生成的切片将与 windows 的参数大小相同,因此可以直接访问元素只要索引小于窗口大小,就按索引。

    使用Iterator::zip

    您可以使用Vec 和std::iter::Zip 相同的两个不同迭代器将当前元素与下一个元素进行比较。

    来自第一个迭代器 (data.iter()) 的迭代器元素将代表当前元素。第二个迭代器 (data.iter().skip(1)) 中的元素将代表下一个元素。

    这里是实现:

    fn main() {
        let data: Vec<Obj> = vec![Obj { i: 0 }, Obj { i: 1 }, Obj { i: 2 }];
    
        let is_valid = data
            .iter()
            .zip(data.iter().skip(1))
            .all(|(current, next)| current.is_valid_next(next));
    
        println!("Is consecutive -> {:?}", is_valid); // true
    }
    

    Playground

    如果您确定您的Vec 不为空,您可以使用切片来创建迭代器:&amp;data[1..] 而不是data.iter().skip(1) (sample)。如果您有一个空的Vec,这将导致恐慌。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 1970-01-01
      • 2020-12-25
      相关资源
      最近更新 更多