【问题标题】:Is it possible to split a vector into groups of 10 with iterators?是否可以使用迭代器将向量分成 10 个组?
【发布时间】:2018-04-02 16:51:58
【问题描述】:

我有 let my_vec = (0..25).collect::<Vec<_>>(),我想将 my_vec 拆分为 10 组的迭代器:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
[20, 21, 22, 23, 24, None, None, None, None, None];

Rust 中的迭代器可以做到这一点吗?

【问题讨论】:

    标签: vector iterator rust


    【解决方案1】:

    Iterator trait 上直接没有这样的辅助方法。但是,有两种主要方法可以做到这一点:

    1. 使用[T]::chunks() method(可以直接在Vec<T> 上调用)。但是,它有一个细微的区别:它不会产生None,但最后一次迭代会产生更小的切片。

      Example:

      let my_vec = (0..25).collect::<Vec<_>>();
      
      for chunk in my_vec.chunks(10) {
          println!("{:02?}", chunk);
      }
      

      结果:

      [00, 01, 02, 03, 04, 05, 06, 07, 08, 09]
      [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
      [20, 21, 22, 23, 24]
      
    2. 使用the crate itertools 中的Itertools::chunks() method。这个 crate 扩展了标准库中的 Iterator 特征,所以这个 chunks() 方法适用于所有迭代器!请注意,为了通用,用法稍微复杂一些。这与上述方法具有相同的行为:在最后一次迭代中,块将更小而不是包含Nones。

      Example:

      extern crate itertools;
      use itertools::Itertools;
      
      for chunk in &(0..25).chunks(10) {
          println!("{:02?}", chunk.collect::<Vec<_>>());
      }
      

      结果:

      [00, 01, 02, 03, 04, 05, 06, 07, 08, 09]
      [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
      [20, 21, 22, 23, 24]
      

    【讨论】:

    • 谢谢!第一个解决方案正是我想要的
    【解决方案2】:

    您可以仅使用标准库实现与Lukas Kalbertodt's itertools example 类似的解决方案:

    let my_vec = (0..25).collect::<Vec<_>>();
    
    let mut my_values = my_vec.into_iter().peekable();
    
    while my_values.peek().is_some() {
        let chunk: Vec<_> = my_values.by_ref().take(10).collect();
        println!("{:?}", chunk);
    }
    

    结果:

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    [20, 21, 22, 23, 24]
    

    如果你实际上并不需要每个块的Vec,你可以省略collect调用,直接对by_ref创建的迭代器进行操作。

    另见:

    【讨论】:

      【解决方案3】:

      我从 Python 改编来获得 groupby() 效果的一个技巧,就像 Python 的 itertools 提供的那样,是使用 .zip().skip().step_by() 组合两个或多个迭代器。这种方法可以生成 10 个组,但是在代码库中看到会非常不美观。但如果您需要小团体,这可能没问题。

      Rust 确实有 itertools crate 和 .group_by(),但根据情况并不总是可用 - 例如,向 HackerRank 等网站提交 Rust 解决方案。

      fn main()
      {
          let a = "Hello, World!";
      
          println!("{:?}", a.chars().step_by(2).zip(
                               a.chars().skip(1).step_by(2) 
                           ).collect::<Vec<_>>());
      }
      

      输出:

      [('H', 'e'), ('l', 'l'), ('o', ','), (' ', 'W'), ('o', 'r'), ('l', 'd')]
      

      其中n 是压缩迭代器的数量,.step_by 的值将是所有迭代器的n.skip() 的值将取决于迭代器在链中的位置;第一个迭代器将跳过 0,下一个 1,等等。

      您可以通过这种方式链接任意数量的迭代器,但是在第三个之后它开始看起来有点复杂和丑陋。在这种情况下,也许考虑将迭代器收集到 Vec 并使用其 .chunks() 方法。或者,如果可以,请使用 itertools crate。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-29
        • 1970-01-01
        • 2013-08-01
        • 1970-01-01
        • 2020-11-13
        相关资源
        最近更新 更多