【问题标题】:Filtering and reducing lazy structures过滤和减少惰性结构
【发布时间】:2021-02-13 23:11:55
【问题描述】:

我想filter 一个惰性结构,然后reduce 它使用 Swift 语言。

func main() -> () {
    let result = (1...)
        .lazy
        .filter { $0 < 3 }
        .reduce(0, {$0 + $1})
    return print(
        result
    )
}

main()

此代码编译;但是,程序没有以正确的方式执行(花费太长时间)。屏幕上的打印结果应该是3。 有没有办法实现这个目标?

【问题讨论】:

  • (1...) 不是数组
  • 你是对的。更正它。
  • 感谢@Leo Dabus 的提问。我试图了解如何reduce 一个惰性结构。

标签: swift generics lazy-evaluation lazy-sequences


【解决方案1】:

问题不在于您的序列是惰性的,而在于您的序列是无限的。您可能正在寻找 sequence 方法。示例:

let s = sequence(first: 0) {
    $0 > 3 ? nil : $0 + 1
}
let result = s.reduce(0) { $0 + $1 }
print(result) // 10

slazy 并且是可能无限但实际上无限,因为生成系列中的下一个项目的方法通过返回提前退出nil 当序列超过 3 时。这与您的 filter 类似,只是它不是过滤器,而是停止器。您可以在此处使用您喜欢的任何条件来生成停止器。

【讨论】:

  • 或带有中断的常规 for 循环。 for x in 1... {if x &lt; 3 {result += 1} else {break}}
  • 非常感谢@matt!我理解了这个概念。顺便说一句,我前段时间给你买了《AppleScript:权威指南》一书,学到了很多:-)
  • 带回了回忆! :)
【解决方案2】:

要让程序终止,您需要在原始序列(1...) 上添加一个上限。

正如它所写的,你有一个无限的数字序列,从1 开始。以下运算符——尤其是filter——无法“知道”一旦它们通过3,它们就可以丢弃序列的其余部分。他们必须处理整个无限序列,过滤掉除前两个元素之外的所有元素,然后您的reduce 才能产生最终结果并打印出来。 (实际上,您最终会溢出 Int,因此程序会在那时终止,但这并不是一件真正值得依赖的事情。)

如果您不想更改原始 (1...),您可以通过将 filter 替换为 prefix 来近似相同的行为。过滤器必须查看每个元素;前缀可以“知道”它在一定数量的元素之后停止。例如,它运行得非常快并打印出3

let result = (1...)
    .lazy
    .prefix(2)
    .reduce(0) {$0 + $1}

【讨论】:

  • 谢谢你,@Tim。那么,没有办法减少惰性结构吗?问题是:我事先不知道过滤后会剩下多少元素。
  • @F.Zer 编译器和运行时都没有。这与序列是惰性的事实无关;这与序列是无限的事实有关。完全不清楚这里的目标应该是什么。
猜你喜欢
  • 1970-01-01
  • 2019-10-16
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
  • 2021-07-05
  • 2020-01-05
相关资源
最近更新 更多