为包装其他两个已排序集合的Swift集合计算向后索引

为包装其他两个已排序集合的Swift集合计算向后索引,swift,collections,bidirectional,Swift,Collections,Bidirectional,我接受了其他人的任务,创建一个序列,该序列包装给定的排序序列,并过滤掉属于第二个给定排序序列的元素,同时也给出了用于排序的谓词。我写过渴望和懒惰的版本。如果主序列和筛选器序列都是集合,则延迟版本支持集合 public struct LazyPresortedSubtractionSequence<Base: Sequence, Filter: Sequence> where Base.Element == Filter.Element { /// The sequence w

我接受了其他人的任务,创建一个序列,该序列包装给定的排序序列,并过滤掉属于第二个给定排序序列的元素,同时也给出了用于排序的谓词。我写过渴望和懒惰的版本。如果主序列和筛选器序列都是集合,则延迟版本支持集合

public struct LazyPresortedSubtractionSequence<Base: Sequence, Filter: Sequence> where Base.Element == Filter.Element {
    /// The sequence where the vended elements come from.
    var base: Base
    /// The sequence where matches to be filtered come from.
    var filters: Filter
    /// The closure for determining the relative order of elements.
    let areInIncreasingOrder: (Base.Element, Base.Element) -> Bool
    /// Creates a sequence vending elements of a given base sequence minus the elements that are also in another sequence.
    init(_ base: Base, filter: Filter, by areInIncreasingOrder: @escaping (Base.Element, Base.Element) -> Bool) {
        self.base = base
        filters = filter
        self.areInIncreasingOrder = areInIncreasingOrder
    }
}

//...

public typealias LazyPresortedSubtractionCollection<Base: Collection, Filter: Collection> = LazyPresortedSubtractionSequence<Base, Filter> where Base.Element == Filter.Element

extension LazyPresortedSubtractionCollection: Collection {
    public struct Index: Comparable {
        /// The targeted element in the base collection.
        public let index: Base.Index
        /// The next unused filter element when the target element is chosen.  Meant to be a cache to calculate the next index, not significant for direct use.
        let filterIndex: Filter.Index
        public static func == (lhs: Index, rhs: Index) -> Bool {
            return lhs.index == rhs.index
        }
        public static func < (lhs: Index, rhs: Index) -> Bool {
            return lhs.index < rhs.index
        }
    }

    /// Find the first element of `base`'s suffix to not be filtered out by elements in `filter`'s suffix, without using loops.
    private func nextIndex(baseStart: Base.Index, filterStart: Filter.Index) -> Index {
        guard baseStart < base.endIndex, filterStart < filters.endIndex, !areInIncreasingOrder(base[baseStart], filters[filterStart]) else {
            return Index(index: baseStart, filterIndex: filterStart)
        }

        let incrementBase = !areInIncreasingOrder(filters[filterStart], base[baseStart])
        let nextBaseIndex = base.index(baseStart, offsetBy: incrementBase ? +1 : 0)
        return nextIndex(baseStart: nextBaseIndex, filterStart: filters.index(after: filterStart))
    }

    /**
     The position of the first element in a nonempty collection.

     If the collection is empty, `startIndex` is equal to `endIndex`.

     - Warning: Since the collection filters elements and can't cache the result (since the properties involved are conditional), the computation is linear instead of constant.

     - Complexity: O(_n_ + _k_), where *n* is the element count of the wrapped collection and *k* is the element count of the filter collection.
     */
    public var startIndex: Index {
        return nextIndex(baseStart: base.startIndex, filterStart: filters.startIndex)
    }
    public var endIndex: Index {
        // The value for `filterIndex` may be wrong for some collections, but it's not used in comparisons.
        // (By wrong, I mean `index(after: indices.last).filterIndex` may be before `filters.endIndex`.  This may happen when `base.last` is less than `filters.last`.)
        return Index(index: base.endIndex, filterIndex: filters.endIndex)
    }
    public subscript(position: Index) -> Base.Element {
        return base[position.index]
    }
    public func index(after i: Index) -> Index {
        return nextIndex(baseStart: base.index(after: i.index), filterStart: i.filterIndex)
    }
}
在索引元素之前,您需要找出两个内部集合中存在多少重复值,并且仅当主集合的值多于筛选器集合时才包含上一个值,否则继续。这让我很难理解,至少我必须将过滤器集合索引与主集合索引同步,但要向后!这可能吗?请记住,这两个内部集合都已根据同样存储的排序谓词进行排序

extension LazyPresortedSubtractionCollection: BidirectionalCollection where Base: BidirectionalCollection, Filter: BidirectionalCollection {
    public func index(before i: Index) -> Index {
        // What goes here?
    }
}