我正在尝试编写一个函数,该函数在给定子序列的首次出现时返回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
?
答案 0 :(得分:2)
您只需要将返回类型声明为Self.SubSequence?
。您还需要为在firstIndex(of:)
扩展名中使用的Collection
s定义Array
方法。我已经定义了它只是为了能够编译代码,但是如果您的逻辑不同,请随时更改实现。
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]
}
}
答案 1 :(得分:0)
首先,让我们修复firstOccuranceOf(subsequence:)
上定义的Array
:
//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
}
}