我的程序将集合表示为Iterator<Range<usize>>
,我正在尝试实现集合减法。
基本上,我正在尝试创建一个函数set_diff
,以便:
let a = vec![1..5, 7..10];
let a = a.into_iter();
let b = vec![3..9];
let b = b.into_iter();
let mut c = set_diff(a, b);
assert_eq!(c.next(), Some(1..3));
assert_eq!(c.next(), Some(9..10));
assert_eq!(c.next(), None);
这个代码应该与#[no_std]
一起运行,这很复杂。真正的迭代器a
和b
能够克隆,如果有帮助的话。
我为下面两个范围的差异制作了一个可能正常工作的迭代器。我想到的唯一可能的解决方案是在B的每个元素上对每个元素进行平面映射,但这样效率非常低。
use std::cmp::{max, min};
use std::ops::Range;
/// An extension for Ranges allowing subtraction.
pub trait RangeExt<T: Ord> {
fn difference(self, other: Self) -> DiffIter<T>;
}
impl RangeExt<usize> for Range<usize> {
fn difference(self, other: Range<usize>) -> DiffIter<usize> {
DiffIter {
state: Some(match (self.start < other.start, self.end < other.end) {
(false, false) => DiffIterState::One(Range {
start: max(other.end, self.start),
end: self.end,
}),
(false, true) => DiffIterState::None,
(true, false) => DiffIterState::Two(Range {
start: self.start,
end: other.start,
}, Range {
start: other.end,
end: self.end,
}),
(true, true) => DiffIterState::One(Range {
start: self.start,
end: if other.start == self.end {
self.end
} else {
min(other.start - 1, self.end)
}
}),
})
}
}
}
/// A iterator for the difference of two ranges.
pub struct DiffIter<T> {
state: Option<DiffIterState<T>>,
}
impl<T> Iterator for DiffIter<T> {
type Item = Range<T>;
fn next(&mut self) -> Option<Range<T>> {
let (out, next) = match self.state.take().unwrap() {
DiffIterState::None => {
(None, DiffIterState::None)
},
DiffIterState::One(r) => {
(Some(r), DiffIterState::None)
},
DiffIterState::Two(l, r) => {
(Some(l), DiffIterState::One(r))
},
};
self.state = Some(next);
out
}
}
enum DiffIterState<T> {
None,
One(Range<T>),
Two(Range<T>, Range<T>),
}