【问题标题】:How do I use a Peekable iterator in a filter closure?如何在过滤器闭包中使用 Peekable 迭代器?
【发布时间】:2017-12-05 01:05:09
【问题描述】:

我只需要找到下一个数字相同的数字:[1,2,2,3,4,4] 应该产生 [2,4]。由于我需要查看下一个数字,我想我会尝试使用Peekable iterator 并写一个filter

fn main() {
    let xs = [1, 2, 2, 3, 4, 4];
    let mut iter = xs.iter().peekable();

    let pairs = iter.filter(move |num| {
        match iter.peek() {
            Some(next) => num == next,
            None       => false,
        }
    });

    for num in pairs {
        println!("{}", num);
    }
}

我收到一个错误:

error[E0382]: capture of moved value: `iter`
 --> src/main.rs:6:15
  |
5 |     let pairs = iter.filter(move |num| {
  |                 ---- value moved here
6 |         match iter.peek() {
  |               ^^^^ value captured here after move
  |
  = note: move occurs because `iter` has type `std::iter::Peekable<std::slice::Iter<'_, i32>>`, which does not implement the `Copy` trait

我认为这是因为 iter 正在被闭包使用,但它没有借用它,也无法复制它。

如何解决想要在过滤器中引用迭代器的问题?

【问题讨论】:

    标签: iterator rust


    【解决方案1】:

    引用过滤器内的迭代器

    我不相信你可以。当您调用filter 时,它会获得基迭代器的所有权:

    fn filter<P>(self, predicate: P) -> Filter<Self, P> 
    where
        P: FnMut(&Self::Item) -> bool, 
    

    一旦你这样做了,它就消失了。没有更多的iter。在一些类似的情况下,您可以使用Iterator::by_ref 可变地借用迭代器,驱动它一段时间,然后再参考原来的。这在这种情况下不起作用,因为内部迭代器需要第二次可变地借用它,这是不允许的。

    只查找下一个数字相同的数字。

    extern crate itertools;
    
    use itertools::Itertools;
    
    fn main() {
        let input = [1, 2, 2, 3, 4, 4];
    
        let pairs = input
            .iter()
            .tuple_windows()
            .filter_map(|(a, b)| if a == b { Some(a) } else { None });
    
        let result: Vec<_> = pairs.cloned().collect();
        assert_eq!(result, [2, 4]);
    }
    

    或者如果你想要只使用标准库的东西:

    fn main() {
        let xs = [1, 2, 2, 3, 4, 4];
    
        let mut prev = None;
        let pairs = xs.iter().filter_map(move |curr| {
            let next = if prev == Some(curr) { Some(curr) } else { None };
            prev = Some(curr);
            next
        });
    
        let result: Vec<_> = pairs.cloned().collect();
        assert_eq!(result, [2, 4]);
    }
    

    【讨论】:

    • 在切片的特定情况下,.windows() 产生一个子切片作为窗口,虽然不是通用的,但它相对等效于 tuple_windows
    猜你喜欢
    • 2015-01-07
    • 2017-08-05
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    • 2015-02-23
    相关资源
    最近更新 更多