微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么在迭代器上使用过滤器时会得到不同的参数类型?

如何解决为什么在迭代器上使用过滤器时会得到不同的参数类型?

我正在使用 filter,但我不明白为什么我应该将 **x > 1 用于切片,而将 *x > 1 用于范围。

fn main() {
    let a = [0,1,2,3];
    let a_iter = a.iter().filter(|x: &&i32| **x > 1);  // x: &&i32
    let x: Vec<&i32> = a_iter.collect();
    println!("{:?}",x);

    let b = 0..4;
    let b_iter = b.filter(|x: &i32| *x > 1);           // x: &i32
    let y: Vec<i32> = b_iter.collect();
    println!("{:?}",y);
}

The docs 说它应该是 **x > 1

解决方法

slice::iter,例如您的示例中的 a.iter(),在对值的引用上生成迭代器。 Range 是产生非引用值的迭代器。

filter(<closure>) 方法采用 <closure>,它通过引用获取迭代器值,因此如果您的迭代器已经生成引用,您将获得对引用的引用,如果您的迭代器生成非引用值然后您将获得对这些值的引用。

如果我们在两个示例中都使用 Vec,区别会变得更容易理解:

fn main() {
    let a = vec![0,1,2,3];
    let a_iter = a.iter(); // iter() returns iterator over references
    let x: Vec<&i32> = a_iter.filter(|x: &&i32| **x > 1).collect();
    println!("{:?}",x);

    let b = vec![0,3];
    let b_iter = a.into_iter(); // into_iter() returns iterator over values
    let y: Vec<i32> = b_iter.filter(|x: &i32| *x > 1).collect();
    println!("{:?}",y);
}

playground

,

这是因为在数组示例中,您首先调用 .iter() 来创建一个迭代器,它借用数组并因此借用其中的值; filter 的闭包参数接收迭代器 Item 的借用版本,因此再次借用它,使其成为 &&i32

Range 的情况下,您直接调用 filter,因为 Range is 是一个迭代器。因此,迭代器包含拥有的值,而 filter 中的闭包借用了它,这使得它的类型为 &i32

你可以看到,如果你在 let y = b; 行之后尝试 let b_iter = ...:你会得到一个 use of moved value 错误,因为 b 被你的迭代器消耗了用于b.filter

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。