相关疑难解决方法(0)

为什么在懒惰地评估过滤器(_ :)的谓词被调用了这么多次?

我看到一个答案了这个问题,它在它的第一个版本,也有类似的代码如下:

let numbers = Array(0 ..< 50)

let result = numbers.lazy
    .filter {
        // gets called 2-3x per element in the range (0...15)!
        print("Calling filter for: \($0)")
        return $0 % 3 == 0
    }
    .prefix(5)

print(Array(result)) // [0, 3, 6, 9, 12]
Run Code Online (Sandbox Code Playgroud)

通过使用惰性过滤器集合,它能够过滤numbers满足给定谓词的前5个元素(在这种情况下,可被3整除),而无需评估数组中的每个元素numbers.

然而,答案然后指出,filter(_:)每个元素可以多次调用谓词(范围1 ... 15中的元素为3次,结果为0时为2).

这种过滤器的惰性评估效率低下的原因是什么?有没有办法避免多次评估同一元素?

swift

9
推荐指数
1
解决办法
397
查看次数

序列()上的 compactMap 不懒惰?

每隔一段时间,我必须沿着响应者链向上走才能到达已知类的实例。(只是为了这个问题接受这个。)我一直在用一个 while 循环来做这个,但我突然想到使用它会更酷sequence(),它可以像这样巧妙地表达响应者链本身:

let chain = sequence(first: someView as UIResponder) {$0.next}
Run Code Online (Sandbox Code Playgroud)

这太棒了,因为到目前为止我们还没有真正走路;序列是惰性的,在我们开始请求元素之前不会执行匿名函数。为了证明这一点,让我用打印语句检测该代码:

let chain = sequence(first: someView as UIResponder) {r in print(r); return r.next}
Run Code Online (Sandbox Code Playgroud)

好的,假设我正在寻找链中的第一个 ViewController 实例。我可以这样找到它:

if let vc = (chain.first {$0 is ViewController}) as? ViewController {
    print(vc)
}
Run Code Online (Sandbox Code Playgroud)

打印输出显示惰性仍然存在:我们沿着响应者链向上走,直到到达 ViewController 并停止。完美的!在花括号内,vc输入为 ViewController,我们就开始比赛了。

然而,它不会逃脱你的注意,那是丑陋的。我正在测试和铸造。有没有一种方法可以让我在不测试的情况下进行转换并且仍然以 ViewController 结束?

这是优雅的,它工作正常:

for case let vc as ViewController in chain {
    print(vc)
    break
}
Run Code Online (Sandbox Code Playgroud)

这很可爱,而且保持着懒惰——但我必须记得break在最后说,这会毁了一切。

好吧,当我想到这一点时,我真的充满希望:

if let vc = (chain.compactMap{ $0 as? ViewController }.first) {
    print(vc)
} …
Run Code Online (Sandbox Code Playgroud)

lazy-sequences swift

4
推荐指数
1
解决办法
277
查看次数

标签 统计

swift ×2

lazy-sequences ×1