我正试图编写一个函数,该函数在给定子序列的第一次出现时返回Collection
Slice
。
我已经设法将其写成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
}
}