如何有条件地链接迭代器?

4 iterator rust

假设我有:

let it = [1, 2, 3].into_iter();
let jt = [4, 5, 6].into_iter();
let kt = [7, 8, 9].into_iter();
Run Code Online (Sandbox Code Playgroud)

然后我有布尔条件ij并且k。我想生成一个迭代器,它根据it,jtkt的值有条件地将i,j和链接在一起k。我可以仅使用内置的 RustIterator功能来做到这一点吗?

Pen*_*wen 8

你可以制作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);
Run Code Online (Sandbox Code Playgroud)

如果条件为 false,则condition.then_some(...)返回None,生成一个空迭代器。否则Some(...)返回 a。into_iter().flatten()将转变Option<impl IntoIterator<Item=T>>impl Iterator<Item=T>.


cam*_*024 5

如果您想使用裸迭代器,您将遇到一个小问题:

如果你写下下面的内容:

let iter = [1, 2, 3].into_iter();
let iter = if some_condition {
  iter.chain([4, 5, 6])
} else {
  iter
}
Run Code Online (Sandbox Code Playgroud)

你会得到一个错误,归结为:

  = note: expected struct `std::iter::Chain<std::array::IntoIter<_, _>, std::array::IntoIter<{integer}, 3>>`
             found struct `std::array::IntoIter<_, _>`
Run Code Online (Sandbox Code Playgroud)

iter有类型IntoIter, 但iter.chain()有类型Chain<IntoIter, ...>

为了解决这个问题,您有以下几种选择:

  • 你可以使用 Trait 对象,它的行为有点interface像 Java 等语言,但会损失一些性能:
  = note: expected struct `std::iter::Chain<std::array::IntoIter<_, _>, std::array::IntoIter<{integer}, 3>>`
             found struct `std::array::IntoIter<_, _>`
Run Code Online (Sandbox Code Playgroud)
  • 或者,如果您可以牺牲懒惰,可能更好的解决方案是只使用Vec
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]));
}
Run Code Online (Sandbox Code Playgroud)