break out of filter() function



我想优化依赖filter()的函数。在某些情况下,当它们达到某个元素时,我想打破它们。(例如,我可能有一个不同元素的数组。或者,我只想实现一种findFirst功能。)在这种情况下,函数持续到数组结束似乎效率很低。

循环很容易做到这一点,但我想将优化应用于函数式编程原理。(编译器本身无法执行这样的优化,因为它不知道我的数组和我的意图。)

这能做到吗?

有一个first(where:),当它发现第一个通过的案例时就会爆发:

let data = ["Alpha","Beta","Gamma","Delta"]
let b2 = data.first(where:{$0=="Beta"})

filter并不是为了这样爆发而编写的。我不相信有一种开箱即用的方式来做你想要的那种事情。

通常情况下,最好避免使功能更灵活,以涵盖狭窄的情况。添加早期保释有时可能很有用,但会以使filter复杂化为代价,而且代码可能很难阅读(请记住,使用filtermap等函数的主要目标之一是使代码更容易阅读,并确保代码是正确的)。不过,有些函数确实支持提前退出,因为这对它们的目的至关重要,例如containsindexOf

但创建自己的高阶函数来做你想做的事情并不难,它的名字让它们的意图非常清晰。例如,要将序列中的所有元素都取到与模式不匹配的第一个元素,可以这样写takeWhile

extension SequenceType {
    func takeWhile(condition: Generator.Element -> Bool) -> [Generator.Element] {
        var result: [Generator.Element] = []
        for x in self {
            guard condition(x) else { break }
            result.append(x)
        }
        return result
    }
}

let nums = [1,3,1,2]
let isOdd = { $0%2 == 1 }
let initialOdd = nums.takeWhile(isOdd)
print(initialOdd)

使用filter的目的是去掉谓词并扫描整个集合。在浏览整个数据集之前,您无法找到要筛选的数据。在其基本形式中,过滤器只是对一个条件(谓词)的检查,以构建一个新的集合:

let bools = [true, false, false, true]
print(bools.filter {$0})

你所要求的是在实现filter时获得对filter中迭代器循环的控制,以通过隐藏它来简化它。我建议你使用该语言中构建的控制流语句(if、for等、continue、break)来满足你的需要。强制使用奇怪的语法语句是没有意义的,因为这些语句会使代码看起来更加复杂和不可滚动。

最新更新