【问题标题】:Returning a Collection's Slice type返回集合的切片类型
【发布时间】:2019-04-09 17:35:42
【问题描述】:

我正在尝试编写一个函数,该函数返回一个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

【问题讨论】:

  • ????请记住,不能订购集合
  • @XmasRights 您是否正在寻找整个 subsequence 作为数组的子集?还是只是它的第一个元素?
  • @Carpsen90 返回的切片应该是整个子序列的窗口
  • 正如您为数组定义的那样,只有第一个元素应该是原始数组的一部分。所以firstOccuranceOf(subsequence:) 的定义必须先修复
  • @Carpsen90 我对firstIndexOf(subsequence:) 的实现不包括在内,但它确实只在找到整个子序列时才返回索引值。 (它本质上是遍历数组调用starts(with:)

标签: swift collections slice


【解决方案1】:

您只需将返回类型声明为Self.SubSequence?。您还需要为您在Array 扩展中使用的Collections 定义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(1...10).firstOccurence(of: [6, 300,])?无论如何,您应该确保您的endIndex 不超过self.endIndex
  • Array(1...10).firstOccurence(of: [6, 300]) 将返回 nilArray(1...10).firstOccurance(of: [2, 3]) 将返回一个 ArraySlice,它指向匹配序列的第一次出现。现在,目的是验证是否存在,并检查开始和结束索引
  • @XmasRights 根据这个答案,它会返回[6, 7]
  • @Carpsen90 正如我在回答中所述,firstIndex(of:) 函数的实现可能需要更改以符合 OP 的要求,因为它们没有在问题中说明。但是,问题根本不在于逻辑,而在于如何修改现有函数以在Collections 上工作。我只包含了firstIndex(of:) 函数以便能够编译代码。
【解决方案2】:

首先,让我们修复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
    }
}

【讨论】:

    猜你喜欢
    • 2013-08-25
    • 1970-01-01
    • 2011-05-17
    • 1970-01-01
    • 2022-06-10
    • 2011-06-06
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    相关资源
    最近更新 更多