我试图走一对迭代器。这在概念上看起来非常微不足道,但实际上却没有表达出来。
fn next(&mut self) -> Option<Self::Item> {
let mut left = self.left.next();
let mut right = self.right.next();
loop {
match (left, right) {
(Some(left_value), Some(right_value)) => {
match left_value.cmp(&right_value) {
Ordering::Equal => return Some((left_value, right_value)),
Ordering::Less => left = self.left.next(),
Ordering::Greater => right = self.right.next(),
}
}
_ => return None
}
}
}
这不起作用,因为当我匹配时左右移动。有什么方法可以成功表达这一点?
示例(也称为整个箱子):
use std::cmp::{Eq, Ord, Ordering};
pub trait AscendingIterator: Iterator where <Self as Iterator>::Item: Eq + Ord {}
pub trait DescendingIterator: Iterator where <Self as Iterator>::Item: Eq + Ord {}
pub struct AscendingIntersection<T, T1, T2>
where T: Eq + Ord,
T1: AscendingIterator<Item = T>,
T2: AscendingIterator<Item = T>
{
left: T1,
right: T2,
}
impl<T, T1, T2> Iterator for AscendingIntersection<T, T1, T2>
where T: Eq + Ord,
T1: AscendingIterator<Item = T>,
T2: AscendingIterator<Item = T>
{
type Item = (T, T);
fn next(&mut self) -> Option<Self::Item> {
let mut left = self.left.next();
let mut right = self.right.next();
loop {
match (left, right) {
(Some(left_value), Some(right_value)) => {
match left_value.cmp(&right_value) {
Ordering::Equal => return Some((left_value, right_value)),
Ordering::Less => left = self.left.next(),
Ordering::Greater => right = self.right.next(),
}
}
_ => return None,
}
}
}
}
编辑:我为这个懒惰的例子道歉;我可以做的打字数量受到无关的骑车伤害的限制。
答案 0 :(得分:2)
您的match (left, right)
移出left
和right
的值,因此在下一次迭代中它们为空。那么为什么不把它们搬回去呢?
Ordering::Less => {
left = self.left.next();
right = Some(right_value);
},
Ordering::Greater => {
left = Some(left_value);
right = self.right.next();
},
现在,这仍然有点难看。一个更好的方法是完全删除match
。先窃取try_opt!
- 我使用了http://crumblingstatue.github.io/doc/try_opt/src/try_opt/lib.rs.html#1-37
macro_rules! try_opt {
($e:expr) =>(
match $e {
Some(v) => v,
None => return None,
}
)
}
然后就这样做
let mut left = try_opt!(self.left.next());
let mut right = try_opt!(self.right.next());
loop {
match left.cmp(&right) {
Ordering::Equal => return Some((left, right)),
Ordering::Less => left = try_opt!(self.left.next()),
Ordering::Greater => right = try_opt!(self.right.next()),
}
}