我有let my_vec = (0..25).collect::<Vec<_>>(),我想把my_vec分成10个组的迭代器:
let my_vec = (0..25).collect::<Vec<_>>()
my_vec
[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中的迭代器可以做到这一点吗?
bvn4nwqk1#
在Iterator trait上没有这样的helper方法。但是,有两种主要方法可以做到这一点:1.使用**[T]::chunks()方法(可直接在Vec<T>上调用),但有一个细微的区别:它不会产生None,但最后一次迭代会产生一个更小的切片。对于总是精确的切片,如果它不完整,则忽略最后一个块,请参阅[T]::chunks_exact()**方法。Example:
Iterator
[T]::chunks()
Vec<T>
None
[T]::chunks_exact()
let my_vec = (0..25).collect::<Vec<_>>(); for chunk in my_vec.chunks(10) { println!("{:02?}", chunk); }
结果:
```none [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]
1.使用[the crate `itertools`](https://crates.io/crates/itertools)中的**`Itertools::chunks()`**方法。这个crate扩展了标准库中的`Iterator` trait,所以这个`chunks()`方法适用于所有迭代器!注意,为了通用,用法稍微复杂一些。这与上面描述的方法具有相同的行为:在最后一次迭代中,块将更小,而不是包含`None` s。 [Example](https://play.rust-lang.org/?gist=de485e2ea81a861f649fe6fea5fbd89f&version=stable):
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]
sz81bmfz2#
您可以只使用标准库来实现与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创建的迭代器进行操作。参见:
Vec
collect
by_ref
g2ieeal73#
我从Python中改编了一个技巧,以获得像Python的itertools提供的groupby()效果,即使用.zip(),.skip()和.step_by()合并两个或更多迭代器。这种方法可以产生10个组,但在代码库中看到它会非常不美观。但如果你需要小组,这可能是好的。Rust确实有itertools板条箱,而.group_by()板条箱有itertools板条箱,但这并不总是可用的,这取决于具体情况--例如,向HackerRank这样的网站提交Rust解决方案。
itertools
groupby()
.zip()
.skip()
.step_by()
.group_by()
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。
n
.step_by
.chunks()
q1qsirdb4#
使用或不使用人造丝分块一个矢量。然后将一些功能Map到每个部分。在下面的示例中,使用了sum函数。
use rayon::prelude::*; fn main() { let my_vec: Vec<_> = (0..25).collect(); let chunk_size = 10; let chunks_without_rayon: Vec<_> = my_vec .chunks(chunk_size) .enumerate() .map(|(i, chunk)| { println!("chunk{i}: {chunk:?}"); chunk.iter().sum::<i32>() }) .collect(); println!("chunks_without_rayon = {chunks_without_rayon:?}\n"); let chunks_with_rayon: Vec<_> = my_vec .par_chunks(chunk_size) .enumerate() .map(|(i, chunk)| { println!("chunk{i}: {chunk:?}"); chunk.iter().sum::<i32>() }) .collect(); println!("chunks_with_rayon: {chunks_with_rayon:?}") }
chunk0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] chunk1: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] chunk2: [20, 21, 22, 23, 24] chunks_without_rayon = [45, 145, 110] chunk0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] chunk1: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] chunk2: [20, 21, 22, 23, 24] chunks_with_rayon: [45, 145, 110]
4条答案
按热度按时间bvn4nwqk1#
在
Iterator
trait上没有这样的helper方法。但是,有两种主要方法可以做到这一点:1.使用**
[T]::chunks()
方法(可直接在Vec<T>
上调用),但有一个细微的区别:它不会产生None
,但最后一次迭代会产生一个更小的切片。对于总是精确的切片,如果它不完整,则忽略最后一个块,请参阅[T]::chunks_exact()
**方法。Example:
结果:
extern crate itertools;
use itertools::Itertools;
sz81bmfz2#
您可以只使用标准库来实现与Lukas Kalbertodt's itertools example类似的解决方案:
结果:
如果实际上不需要每个块的
Vec
,可以省略collect
调用,直接对by_ref
创建的迭代器进行操作。参见:
g2ieeal73#
我从Python中改编了一个技巧,以获得像Python的
itertools
提供的groupby()
效果,即使用.zip()
,.skip()
和.step_by()
合并两个或更多迭代器。这种方法可以产生10个组,但在代码库中看到它会非常不美观。但如果你需要小组,这可能是好的。Rust确实有
itertools
板条箱,而.group_by()
板条箱有itertools
板条箱,但这并不总是可用的,这取决于具体情况--例如,向HackerRank这样的网站提交Rust解决方案。输出:
其中
n
是压缩迭代器的数量,对于所有迭代器,.step_by
的值将是n
,而.skip()
的值将取决于迭代器在链中的位置;第一个迭代器将跳过0、下一个1等。你可以用这种方式链接任何数量的迭代器,但是在第三个之后,它开始看起来有点复杂和丑陋。在这种情况下,也许可以考虑将迭代器收集到
Vec
中并使用它的.chunks()
方法。或者如果可以的话,使用itertools
crate。q1qsirdb4#
使用或不使用人造丝分块一个矢量。
然后将一些功能Map到每个部分。
在下面的示例中,使用了sum函数。
输出: