假设我有:
let it = [1, 2, 3].into_iter();
let jt = [4, 5, 6].into_iter();
let kt = [7, 8, 9].into_iter();然后我有布尔条件i,j和k。我想要生成一个迭代器,它根据it、jt和kt的值将i、j和k有条件地链接在一起。我可以只使用内置的锈蚀Iterator功能来完成这个任务吗?
发布于 2022-11-16 01:55:29
您可以将Option变成迭代器。
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);如果条件为false,则condition.then_some(...)将返回None,生成一个空迭代器。否则将返回一个Some(...)。into_iter().flatten()将把Option<impl IntoIterator<Item=T>>转换为impl Iterator<Item=T>。
发布于 2022-11-16 01:39:32
如果要使用裸迭代器,就会遇到一个小问题:
如果您写了以下内容:
let iter = [1, 2, 3].into_iter();
let iter = if some_condition {
iter.chain([4, 5, 6])
} else {
iter
}您将得到一个错误,可以归结为:
= note: expected struct `std::iter::Chain<std::array::IntoIter<_, _>, std::array::IntoIter<{integer}, 3>>`
found struct `std::array::IntoIter<_, _>`iter有IntoIter类型,但iter.chain()有Chain<IntoIter, ...>类型
为了解决这个问题,你有几个选择:
interface,但是失去了一些性能: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]);
}发布于 2022-11-16 02:14:08
这是对either机箱的一个很好的使用。当左侧和右侧都实现Either时,Iterator实现了Iterator,因此可以很容易地将迭代器链接在一起。
如果有三个迭代器( it、jt和kt )在同一个Item上迭代,并附带布尔( booleans ) i、j和k,那么您可以编写一个函数,将它们链接在一起,如下所示:
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<_>>();给出
[1, 2, 3, 7, 8, 9]如预期的那样。
您可以使用这个游乐场来尝试它。
https://stackoverflow.com/questions/74454140
复制相似问题