为包装其他两个已排序集合的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?
}
}