【问题标题】:Is there a function in Rust equivalent to Java's Stream.Iterate?Rust 中是否有等效于 Java 的 Stream.Iterate 的函数?
【发布时间】:2016-03-10 05:35:25
【问题描述】:

Rust 标准库是否像 Java 8 Streams 提供的那样,具有在给定种子和 lambda 的情况下生成无限迭代器的函数?如果不是,Rust 中有什么类似的替代方案?

Stream.iterate(1, x -> 2 * x);

【问题讨论】:

    标签: iterator rust


    【解决方案1】:

    Rust 标准库 used 在名称 unfold 下具有类似的功能,但它从未变得稳定并最终被删除。它现在住在itertools crate

    extern crate itertools;
    
    use itertools::Unfold;
    
    fn main() {
        let x = Unfold::new(1, |x| {
            *x *= 2;
            Some(*x)
        });
    
        for val in x.take(10) {
            println!("{}", val);
        }
    }
    

    请注意,它有点复杂,因为状态不必与迭代器返回的内容完全匹配,您可以控制迭代器何时停止。板条箱可能会接受 PR 用于顶部的薄层,以提供您的精确实现。

    【讨论】:

      【解决方案2】:

      从 Rust 1.7 开始,Rust 的标准库中没有任何东西相当于 Stream.iterate(或者我找不到它!)。

      我刚刚在 Rust 中创建了以下实现。它不像 Java 实现那么简单,因为我们必须处理所有权(因此需要 CloneOptionvalue 字段共舞)。

      struct SequenceGenerator<T, F> {
          value: Option<T>,
          calc_next: F,
      }
      
      impl<T, F> SequenceGenerator<T, F>
          where T: Clone,
                F: FnMut(T) -> T
      {
          fn new(value: T, calc_next: F) -> SequenceGenerator<T, F> {
              SequenceGenerator {
                  value: Some(value),
                  calc_next: calc_next,
              }
          }
      }
      
      impl<T, F> Iterator for SequenceGenerator<T, F>
          where T: Clone,
                F: FnMut(T) -> T
      {
          type Item = T;
      
          fn next(&mut self) -> Option<T> {
              let result = self.value.as_ref().unwrap().clone();
              self.value = Some((self.calc_next)(self.value.take().unwrap()));
              Some(result)
          }
      }
      
      fn main() {
          let seq_gen = SequenceGenerator::new(1, |x| 2 * x);
          for i in seq_gen.take(10) {
              println!("{}", i);
          }
      }
      

      【讨论】:

      • 这应该包装在一个板条箱中,记录在案并作为 TWiR 本周的板条箱提交。
      • 我想知道用F: FnMut(&amp;mut T)代替take跳舞会不会更容易。
      • itertools crate 已经有这个了吗?似乎应该这样做。
      • valuefn next(&amp;mut self) -&gt; Option&lt;T&gt; { let new_value = (self.calc_next)(&amp;self.value); Some(mem::replace(&amp;mut self.value, new_value)) } 中删除F: FnMut(&amp;mut T)Option 看起来更整洁。
      【解决方案3】:

      你可以使用标准的scan迭代器:

      let seq_gen = iter::repeat(())
                            .scan(1, |r,_|{
                                let out = *r; *r = out * 2 ; Some(out)
                            });
      

      或带有明确的闭包定义:

      let seq_gen = iter::repeat(())
                            .scan((1, |x| x*2), |r,_|{
                                let out = r.0; r.0 = r.1(r.0); Some(out)
                            });
      

      对于 noncopyable 类型,情况看起来更糟:

      let seq_gen = iter::repeat(())
                            .scan(Some("Hello world".to_owned()), |r,_|{
                                let out = r.clone(); *r = r.take().map(|x| x+"!") ; out
                            });
      

      对于这些类型,最好使用修改值的函数:

      let seq_gen = iter::repeat(())
                            .scan("Hello world".to_owned(), |r,_|{
                                let out = r.clone(); r.push_str("!") ; Some(out)
                            });
      

      【讨论】:

      • 不错;但是,对于String,它不会按原样工作,因为您在不知不觉中依赖1Copy 以使let out = r.0 工作恐怕。 scan 的问题在于它并不是真正的这种把戏。当您需要产生 values 时,状态仍然是 scan 的属性。
      • @MatthieuM。但是您可以在迭代器之前声明String,然后使用&amp;mut String 作为状态值,对吧?
      • @Shepmaster:可能......我在之前的答案中使用过&amp;mut Option&lt;T&gt; 之类的东西。它不是很优雅,但我认为它可以工作。
      • @MatthieuM。类似this。还要注意使用iter::repeat 而不是Option iter/cycle。
      • 完全忘记了iter::repeat。 @Shepmaster,谢谢你的提醒。已更新。
      【解决方案4】:

      不知道

      fn main() {
          let x = (1..std::i32::MAX) .map(|x| x*2);
      
          for i in x {
              println!("{}", i);
          }
      }
      

      将是您满意的选择。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 2016-06-28
        • 2011-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-20
        相关资源
        最近更新 更多