gpt4 book ai didi

Scala:有什么理由比 `filter+map` 更喜欢 `collect` 吗?

转载 作者:行者123 更新时间:2023-12-03 09:53:21 25 4
gpt4 key购买 nike

有什么理由更喜欢filter+map :

list.filter (i => aCondition(i)).map(i => fun(i))

collect ? :
list.collect(case i if aCondition(i) => fun(i))

collect 的那个(单看)对我来说看起来更快更干净。所以我总是去 collect .

最佳答案

Scala 的大多数集合都急切地应用操作,并且(除非您使用为您执行此操作的宏库)不会融合操作。所以filter其次是 map通常会创建两个集合(即使你使用 Iterator 或类似的东西,中间形式也会被暂时创建,尽管一次只创建一个元素),而 collect将不会。

另一方面,collect使用偏函数来实现联合测试,偏函数比谓词( A => Boolean )在测试集合中是否有东西时要慢。

此外,在某些情况下,读取一个比另一个更清晰,并且您不关心性能或内存使用差异的 2 倍左右。在这种情况下,使用更清楚的那个。通常,如果您已经命名了函数,则阅读起来会更清晰

xs.filter(p).map(f)
xs.collect{ case x if p(x) => f(x) }

但如果您提供内联闭包, collect通常看起来更干净
xs.filter(x < foo(x, x)).map(x => bar(x, x))
xs.collect{ case x if foo(x, x) => bar(x, x) }

即使它不一定更短,因为您只引用一次变量。

现在,性能差异有多大?这会有所不同,但如果我们考虑这样的集合:
val v = Vector.tabulate(10000)(i => ((i%100).toString, (i%7).toString))

并且您想根据过滤第一个条目选择第二个条目(因此过滤器和映射操作都非常简单),然后我们得到下表。

注意:可以将惰性 View 放入集合并在那里收集操作。您并不总能找回原始类型,但您始终可以使用 to获得正确的集合类型。所以 xs.view.filter(p).map(f).toVector由于 View 的原因,不会创建中间体。这也在下面进行了测试。也有人建议可以 xs.flatMap(x => if (p(x)) Some(f(x)) else None)并且这是有效的。 事实并非如此。 下面也进行了测试。并且可以通过显式创建构建器来避免偏函数: val vb = Vector.newBuilder[String]; xs.foreach(x => if (p(x)) vb += f(x)); vb.result ,其结果也在下面列出。

在下表中,测试了三个条件:不过滤、过滤一半、过滤所有。时间已标准化为过滤器/映射(100% = 与过滤器/映射相同的时间,越低越好)。误差范围约为 +- 3%。

不同过滤器/映射替代方案的性能
====================== Vector ========================
filter/map collect view filt/map flatMap builder
100% 44% 64% 440% 30% filter out none
100% 60% 76% 605% 42% filter out half
100% 112% 103% 1300% 74% filter out all

因此, filter/mapcollect通常非常接近( collect 当你持有很多时获胜), flatMap在所有情况下都慢得多,并且创建构建器总是获胜。 (对于 Vector 尤其如此。其他集合可能有一些不同的特征,但大多数集合的趋势将是相似的,因为操作的差异是相似的。)本次测试中的观点往往是胜利,但他们没有始终无缝工作(并且它们并不比 collect 更好,除了空 shell )。

所以,底线:更喜欢 filter然后 map如果它在速度无关紧要时有助于清晰,或者在您过滤掉几乎所有内容但仍希望保持功能正常时更喜欢它的速度(所以不想使用构建器);否则使用 collect .

关于Scala:有什么理由比 `filter+map` 更喜欢 `collect` 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36961777/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com