有条件地从flat_map返回空迭代器 [英] Conditionally return empty iterator from flat_map
问题描述
鉴于 foo
的定义:
let foo = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
我希望能够编写如下代码:
I'd like to be able to write code like this:
let result: Vec<_> = foo.iter()
.enumerate()
.flat_map(|(i, row)| if i % 2 == 0 {
row.iter().map(|x| x * 2)
} else {
std::iter::empty()
})
.collect();
但是这会引发有关if和else子句不兼容类型的错误。我试图暂时删除 map
,我尝试在闭包外部定义一个空向量并返回一个迭代器,如下所示:
but that raises an error about the if and else clauses having incompatible types. I tried removing the map
temporarily and I tried defining an empty vector outside the closure and returning an iterator over that like so:
let empty = vec![];
let result: Vec<_> = foo.iter()
.enumerate()
.flat_map(|(i, row)| if i % 2 == 0 {
row.iter() //.map(|x| x * 2)
} else {
empty.iter()
})
.collect();
这似乎有些愚蠢,但它编译。如果我尝试取消注释 map
,那么它仍会抱怨if和else子句具有不兼容的类型。以下是错误消息的一部分:
This seems kind of silly but it compiles. If I try to uncomment the map
then it still complains about the if and else clauses having incompatible types. Here's part of the error message:
error[E0308]: if and else have incompatible types
--> src/main.rs:6:30
|
6 | .flat_map(|(i, row)| if i % 2 == 0 {
| ______________________________^
7 | | row.iter().map(|x| x * 2)
8 | | } else {
9 | | std::iter::empty()
10 | | })
| |_________^ expected struct `std::iter::Map`, found struct `std::iter::Empty`
|
= note: expected type `std::iter::Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:7:28: 7:37]>`
found type `std::iter::Empty<_>`
我知道我可以用一些嵌套的为
循环写一些我想要的东西,但是我想知道是否有一种简洁的方法来编写它使用迭代器。
I know I could write something that does what I want with some nested for
loops but I'd like to know if there's a terse way to write it using iterators.
推荐答案
由于Rust是静态类型的,因此迭代器链中的每个步骤都会将结果更改为一个新的类型,其中包含了以前的类型(除非你使用盒装特征对象)你必须以两种分支被相同类型覆盖的方式编写它。
Since Rust is statically typed and each step in an iterator chain changes the result to a new type that entrains the previous types (unless you use boxed trait objects) you will have to write it in a way where both branches are covered by the same types.
传达条件空虚的一种方法单一类型的是 TakeWhile
迭代器实现。
One way to convey conditional emptiness with a single type is the TakeWhile
iterator implementation.
.flat_map(|(i, row)| {
let iter = row.iter().map(|x| x * 2);
let take = i % 2 == 0;
iter.take_while(|_| take)
})
如果你不介意忽略输入迭代器 foo
可能还有 usize
元素的边缘情况使用0或usize :: MAX取
。它的优点是提供了比 TakeWhile
更好的 size_hint()
。
If you don't mind ignoring the edge-case where the input iterator foo
could have more than usize
elements you could also use Take
instead with either 0 or usize::MAX. It has the advantage of providing a better size_hint()
than TakeWhile
.
这篇关于有条件地从flat_map返回空迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!