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

问题描述 投票:1回答:2

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

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>

rust pattern-matching
2个回答
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
投票

这样可行:

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()并使用值。

© www.soinside.com 2019 - 2024. All rights reserved.