两个Iterator <range <usize>&gt;之间的差异

时间:2017-04-10 04:15:34

标签: algorithm rust range

我的程序将集合表示为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]一起运行,这很复杂。真正的迭代器ab能够克隆,如果有帮助的话。

我为下面两个范围的差异制作了一个可能正常工作的迭代器。我想到的唯一可能的解决方案是在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>),
}

0 个答案:

没有答案