let it = i.then_some([1, 2, 3]).into_iter().flatten();
let jt = j.then_some([4, 5, 6]).into_iter().flatten();
let kt = k.then_some([7, 8, 9]).into_iter().flatten();
let iter = it.chain(jt).chain(kt);
let iter = [1, 2, 3].into_iter();
let mut iter: Box<dyn Iterator<Item = i32>> = Box::new(iter);
if some_condition {
iter = Box::new(iter.chain([4, 5, 6]));
}
或者,如果可以牺牲惰性,可能更好的解决方案是使用Vec:
// save heap allocations by pre-allocating the whole vec
let len = if some_condition { 6 } else { 3 };
let mut items = Vec::with_capacity(len);
items.extend([1, 2, 3]);
if some_condition {
items.extend([4, 5, 6]);
}
use either::Either;
use std::iter;
fn chain<'a, I, J, K, Item>(
it: I,
jt: J,
kt: K,
i: bool,
j: bool,
k: bool,
) -> iter::Chain<
iter::Chain<Either<I, iter::Empty<Item>>, Either<J, iter::Empty<Item>>>,
Either<K, iter::Empty<Item>>,
>
where
I: Iterator<Item = Item>,
J: Iterator<Item = Item>,
K: Iterator<Item = Item>,
{
let iter = if i {
Either::Left(it)
} else {
Either::Right(iter::empty())
};
let iter = iter.chain(if j {
Either::Left(jt)
} else {
Either::Right(iter::empty())
});
let iter = iter.chain(if k {
Either::Left(kt)
} else {
Either::Right(iter::empty())
});
iter
}
调用此函数将生成一个基于输入的迭代器条件。
let it = [1, 2, 3].into_iter();
let jt = [4, 5, 6].into_iter();
let kt = [7, 8, 9].into_iter();
chain(it, jt, kt, true, false, true).collect::<Vec<_>>();
3条答案
按热度按时间dgenwo3n1#
你可以把
Option
变成一个迭代器。如果条件为false,则
condition.then_some(...)
将返回None
,生成空迭代器。否则返回Some(...)
。into_iter().flatten()
将Option<impl IntoIterator<Item=T>>
转换为impl Iterator<Item=T>
。nbewdwxp2#
如果你想使用裸迭代器,你会遇到一个小问题:
如果您编写以下内容:
您将得到一个错误,可归结为:
iter
具有IntoIter
类型,但iter.chain()
具有Chain<IntoIter, ...>
类型要解决此问题,您有以下几种选择:
interface
,但会损失一些性能:Vec
:zaqlnxep3#
这是
either
crate的一个很好的用法。当左边和右边都实现Iterator
时,Either
实现Iterator
,所以它可以很容易地用于将迭代器链接在一起。给定任意三个迭代器
it
、jt
和kt
,它们在相同的Item
上迭代,并伴随布尔值i
、j
和k
,你可以编写一个函数,将它们链接在一起,如下所示:调用此函数将生成一个基于输入的迭代器条件。
给予
如所期望的那样。
您可以使用此playground来尝试。