返回集合的切片类型



我正试图编写一个函数,该函数在给定子序列的第一次出现时返回CollectionSlice

我已经设法将其写成Array扩展,因为我知道返回类型将是ArraySlice<Element>,但我很难弄清楚合适的具体输出是什么,使其成为Collection的通用函数

extension Array where Element: Comparable {
func firstOccuranceOf(subsequence: [Element]) -> ArraySlice<Element>? {
guard !subsequence.isEmpty else {
return nil
}
guard let startIndex = self.firstIndexOf(subsequence: subsequence) else {
return nil
}
let endIndex = self.index(startIndex, offsetBy: subsequence.count - 1)
return self[startIndex...endIndex]
}
}

TL;DR:如何将上面的函数重写为extension Collection

您只需要将返回类型声明为Self.SubSequence?。您还需要为Array扩展中使用的Collection定义firstIndex(of:)方法。我定义它只是为了能够编译代码,但如果您的逻辑不同,可以随意更改实现。

extension Collection where Element: Comparable {
func firstIndex(of subsequence: Self) -> Index? {
guard let firstElement = subsequence.first else { return nil }
return self.firstIndex(of: firstElement)
}
func firstOccurence(of subsequence: Self) -> Self.SubSequence? {
guard !subsequence.isEmpty else { return nil }
guard let startIndex = firstIndex(of: subsequence) else { return nil }
let endIndex = index(startIndex, offsetBy: subsequence.count - 1)
return self[startIndex...endIndex]
}
}

首先,让我们按照Array:上的定义修复firstOccuranceOf(subsequence:)

//Only `Equatable` is needed
extension Array where Element: Equatable {
func firstOccurence(of subsequence: [Element]) -> ArraySlice<Element>? {
let subsequenceEndIndex = subsequence.endIndex.advanced(by: -1)
let lastPossibleFirstIndex = endIndex.advanced(by: -subsequenceEndIndex)
for i in indices where i < lastPossibleFirstIndex {
let range = i...i.advanced(by: subsequenceEndIndex)
if Array(self[range]) == subsequence {
return self[range]
}
}
return nil
}
}

它给出:

Array(1...10).firstOccurence(of: [6, 300])  //nil
Array(1...10).firstOccurence(of: [6, 7])    //[6, 7]
Array(1...6).firstOccurence(of: [6, 7])     //nil
let array: [Int] = []
array.firstOccurence(of: [6, 7])            //nil
array.firstOccurence(of: [])                //nil

对于一般集合:

extension Collection where Self: RandomAccessCollection, Element: Equatable {
func firstOccurence(of subsequence: Self) -> Self.SubSequence? {
let subCount = subsequence.count
for i in indices where distance(from: i, to: endIndex) >= subCount  {
let subseq = self.suffix(distance(from: i, to: endIndex)).prefix(subCount)
if Array(subseq) == Array(subsequence) {
return subseq
}
}
return nil
}
}

最新更新