Algorithm 两个迭代器之间的差异<;范围<;使用>&燃气轮机';s
我的程序将集合表示为迭代器,我正在尝试实现集合减法 本质上,我试图创建一个函数Algorithm 两个迭代器之间的差异<;范围<;使用>&燃气轮机';s,algorithm,rust,range,Algorithm,Rust,Range,我的程序将集合表示为迭代器,我正在尝试实现集合减法 本质上,我试图创建一个函数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
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中的每一个元素,在A的每一个元素上进行平面映射,但这确实是低效的
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>),
}
使用std::cmp::{max,min};
使用std::ops::Range;
///允许减法的范围的扩展。
酒吧特征范围{
fn差异(自我,其他:自我)->困难者;
}
范围的impl RangeExt{
fn差异(自身、其他:范围)->DiffIter{
困难者{
状态:部分(匹配(self.startDiffIterState::一(范围{
开始:最大值(另一端,自启动),
结束:self.end,
}),
(false,true)=>DiffIterState::None,
(真、假)=>DiffIterState::2(范围{
开始:self.start,
结束:其他。开始,
},范围{
开始:另一个,
结束:self.end,
}),
(真,真)=>DiffIterState::一(范围{
开始:self.start,
结束:如果other.start==self.end{
自我终结
}否则{
最小值(其他开始-1,自身结束)
}
}),
})
}
}
}
///两个范围之差的迭代器。
pub-struct-DiffIter{
国家:选择权,
}
DiffIter的impl迭代器{
类型项目=范围;
fn下一步(&mut self)->选项{
let(out,next)=匹配self.state.take().unwrap(){
DiffIterState::无=>{
(无,区分状态::无)
},
DiffIterState::一(r)=>{
(部分(r),不同状态::无)
},
二(l,r)=>{
(一些(l),不同的状态::一(r))
},
};
self.state=Some(下一步);
出来
}
}
不同状态枚举{
没有一个
一个(范围),
二(范围,范围),,
}
几个问题:(1)是否保证迭代器的范围不重叠,(2)是否保证它们的范围是有序的,(3)到目前为止您尝试过什么?编辑以显示我在睡觉前尝试过的内容。@MatthieuM(1)是的,(2)我相信A是,B绝对不是,(3)编辑如果B没有排序,您就有麻烦了。我能想到的最简单的解决方案是收集
将所有范围放入一个Vec
,对其进行排序,然后对其进行迭代。不幸的是,Vec
本身无法存储到生成的迭代器中,因此您首先需要创建一个struct
,然后实现IntoIterator
,以生成特殊的迭代器。