【问题标题】:How to generate iterator with sliding window pairs?如何生成带有滑动窗口对的迭代器?
【发布时间】:2021-05-19 21:00:42
【问题描述】:

我想为此输入创建一个迭代器:

[1, 2, 3, 4]

将包含以下内容:

(1, 2)
(2, 3)
(3, 4)

Peekable 似乎很适合这个,但我是 Rust 新手,所以这个幼稚的版本不起作用:

fn main() {
  let i = ['a', 'b', 'c']
    .iter()
    .peekable();
  let j = i.map(|x| (x, i.peek()));
  println!("{:?}", j);
  println!("Hello World!");
}

我做错了什么?

【问题讨论】:

    标签: rust iterator borrow-checker borrowing


    【解决方案1】:

    您可以使用 itertools 板条箱中的 tuple_windows() 作为替代品:

    use itertools::Itertools;
    
    fn main() {
        let data = vec![1, 2, 3, 4];
        for (a, b) in data.iter().tuple_windows() {
            println!("({}, {})", a, b);
        }
    }
    
    (1, 2)
    (2, 3)
    (3, 4)
    

    【讨论】:

      【解决方案2】:

      您可以在切片上使用windows 方法,然后将数组映射为元组:

      fn main() {
          let i = [1, 2, 3, 4]
              .windows(2)
              .map(|pair| (pair[0], pair[1]));
          println!("{:?}", i.collect::<Vec<_>>());
      }
      

      playground


      如果您想要一个适用于所有迭代器(而不仅仅是切片)的解决方案并且愿意使用第 3 方库,您可以使用 itertools 中的 tuple_windows 方法。

      use itertools::{Itertools, TupleWindows}; // 0.10.0
      
      fn main() {
          let i: TupleWindows<_, (i32, i32)> = vec![1, 2, 3, 4]
              .into_iter()
              .tuple_windows();
          println!("{:?}", i.collect::<Vec<_>>());
      }
      

      playground


      如果您不愿意使用 3rd-party 库,它仍然很简单,您可以自己实现它!这是一个适用于任何Iterator&lt;Item = T&gt; 的通用实现示例,其中T: Clone:

      use std::collections::BTreeSet;
      
      struct PairIter<I, T>
      where
          I: Iterator<Item = T>,
          T: Clone,
      {
          iterator: I,
          last_item: Option<T>,
      }
      
      impl<I, T> PairIter<I, T>
      where
          I: Iterator<Item = T>,
          T: Clone,
      {
          fn new(iterator: I) -> Self {
              PairIter {
                  iterator,
                  last_item: None,
              }
          }
      }
      
      impl<I, T> Iterator for PairIter<I, T>
      where
          I: Iterator<Item = T>,
          T: Clone,
      {
          type Item = (T, T);
          fn next(&mut self) -> Option<Self::Item> {
              if self.last_item.is_none() {
                  self.last_item = self.iterator.next();
              }
              if self.last_item.is_none() {
                  return None;
              }
              let curr_item = self.iterator.next();
              if curr_item.is_none() {
                  return None;
              }
              let temp_item = curr_item.clone();
              let result = (self.last_item.take().unwrap(), curr_item.unwrap());
              self.last_item = temp_item;
              Some(result)
          }
      }
      
      fn example<T: Clone>(iterator: impl Iterator<Item = T>) -> impl Iterator<Item = (T, T)> {
          PairIter::new(iterator)
      }
      
      fn main() {
          let mut set = BTreeSet::new();
          set.insert(String::from("a"));
          set.insert(String::from("b"));
          set.insert(String::from("c"));
          set.insert(String::from("d"));
          dbg!(example(set.into_iter()).collect::<Vec<_>>());
      }
      

      playground

      【讨论】:

      • FWIW itertools crate 提供了一个可以按原样使用的 tuple_windows 方法。
      猜你喜欢
      • 2010-10-09
      • 2011-10-12
      • 1970-01-01
      • 2012-10-12
      • 2016-11-25
      • 2019-05-10
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      相关资源
      最近更新 更多