迅速 – 是否有可能缩短对更高级别功能的评估?

我正在寻找一种方法来在评估其部分输入序列后停止更高级别的功能.

当您在满足特定条件的序列中查找第一个索引时,请考虑这种情况.例如,假设我们正在寻找Ints数组中的第一个位置,其中两个连续值的总和大于100.

你可以用循环来做,像这样:

func firstAbove100(a:[Int]) -> Int? {
    if a.count < 2 {
        return nil
    }
    for i in 0..<a.count-1 {
        if a[i]+a[i+1] > 100 {
            return i
        }
    }
    return nil
}

一旦发现感兴趣的位置,循环就会停止.

我们可以使用reduce重写此代码,如下所示:

func firstAbove100(a:[Int]) -> Int? {
    if a.count < 2 {
        return nil
    }
    return (0..<a.count-1).reduce(nil) { prev, i in
        prev ?? (a[i]+a[i+1] > 100 ? i : nil)
    }
}

但是,这种方法的缺点是,即使在第一个索引处找到匹配项,reduce也会一直到a.count-2.结果将是相同的,但削减不必要的工作会很好.

有没有办法让减少停止尝试进一步的匹配,或者可能是一个让你在找到第一场比赛后停止的不同功能?

最佳答案
如上所述,reduce是专门为了评估整个序列而设计的,因此不是为了短路而设计的.以这种方式使用它来查找满足给定谓词的元素的索引最好使用indexOf作为@Casey says.

同样在Swift 3中,现在在Sequence上有第一个(where :)函数,它允许您找到满足给定谓词的第一个元素.这可能是一个比indexOf更合适的替代方案,因为它返回元素而不是索引(尽管在您的特定示例中它们是相同的).

你可以像这样编写你的例子:

func firstAbove100(_ a:[Int]) -> Int? {
    guard a.count > 1 else {return nil}

    return (0..<a.count-1).first { i in
        a[i]+a[i+1] > 100
    }
}

但是,如果你想要一个更通用的高级函数,它将遍历一个序列并在它找到给定谓词的非零结果时突破 – 你总是可以编写自己的find函数:

extension SequenceType {

    func find<T>(@noescape predicate: (Self.Generator.Element) throws -> T?) rethrows -> T? {
        for element in self {
            if let c = try predicate(element) {return c}
        }
        return nil
    }
}

您现在可以像这样编写firstAbove100函数:

func firstAbove100(a:[Int]) -> Int? {
    if a.count < 2 {
        return nil
    }
    return (0..<a.count-1).find { i in
        a[i]+a[i+1] > 100 ? i : nil
    }
}

当它找到一对加到100以上的元素时,它现在会短路.

或者说,不是返回数组中第一对元素的索引,而是添加大于100,您现在想要返回元素的总和.你现在可以像这样写:

func sumOfFirstAbove100(a:[Int]) -> Int? {
    guard a.count > 1 else {return nil}
    return (0..<a.count-1).find { i in
        let sum = a[i]+a[i+1]
        return sum > 100 ? sum : nil
    }
}
let a = [10, 20, 30, 40, 50, 60, 70, 80, 90]
print(sumOfFirstAbove100(a)) // prints: Optional(110)

find函数将遍历数组,将谓词应用于每个元素(在本例中为数组的索引).如果谓词返回nil,那么它将继续迭代.如果谓词返回非nil,那么它将返回该结果并停止迭代.

转载注明原文:迅速 – 是否有可能缩短对更高级别功能的评估? - 代码日志