返回集合的切片类型

时间:2018-11-06 10:25:59

标签: swift collections slice

我正在尝试编写一个函数,该函数在给定子序列的首次出现时返回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

2 个答案:

答案 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
    }
}