我如何匹配“&(& usize,& u32)”这样的模式?

时间:2017-12-29 22:03:34

标签: rust pattern-matching

假设我有素数和幂的向量:

let mut primes: Vec<usize> = ...;
let mut powers: Vec<u32> = ...;

事实是primes.len() == powers.len()

我想向用户返回一个相应功率值为0的素数列表(此代码缺少正确的refs和derefs):

primes.iter().zip(powers)
    .filter(|(p, power)| power > 0)
    .map(|(p, power)| p)
    .collect::<Vec<usize>>()

正如您可能想象的那样,编译器正在抱怨很多。特别是,filter正在接收类型&(&usize, &u32)的参数,但我在模式匹配中没有正确地取消引用。我已经尝试了编译器建议的各种模式(例如&(&p, &power),这是对我来说最有意义的模式),但没有运气。如何正确执行模式匹配,以便我可以毫无问题地进行power > 0比较,以便我最终可以收集Vec<usize>

2 个答案:

答案 0 :(得分:2)

primes.iter().zip(powers)

iter()按引用进行迭代,因此您可以获得素数的&usize个元素。 OTOH .zip()调用.into_iter()来迭代拥有的值,因此幂是u32,并且这些迭代器组合迭代(&usize, u32)。从技术上讲,迭代这种混合类型并没有错,但不一致可能会令人困惑。您可以在素数上使用.into_iter().iter().cloned()来避免引用,或者调用.zip(powers.iter())将两者作为参考。

第二件事是.filter()通过引用&(_,_)获取项目(因为它只“看到”它们),.map()通过拥有值(_,_)(允许它)改变并返回它)。

对于像整数这样的小值,你通常会使用这样的方法:

.filter(|&item| …)
.map(|item| …)

请注意,在闭包中,语法为|pattern: type|,因此在上面的示例中,&item等同于:

.filter(|by_ref| {
   let item = *by_ref;
})

答案 1 :(得分:1)

有效:

fn main() {
  let primes: Vec<usize> = vec![2, 3, 5, 7];
  let powers: Vec<u32> = vec![2, 2, 2, 2];

  let ret = primes.iter().zip(powers.iter())
            .filter_map(|(p, pow)| { // both are refs, so we need to deref
                if *pow > 0 {
                    Some(*p)
                } else {
                    None
                }
            })
            .collect::<Vec<usize>>();

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

请注意,我还使用了powers.iter(),它通过引用生成元素。您还可以在两个迭代器上使用cloned()并使用值。