【问题标题】:Don't return same type from filter for efficiency不要从过滤器返回相同的类型以提高效率
【发布时间】:2020-04-10 02:01:44
【问题描述】:

假设我在 scala 中有一个 Map

Map.filter 返回一个Map。 这意味着它必须创建一个包含过滤器后所有剩余项目的 Map。

由于创建地图通常并不便宜(大约 O(nlog(n))),如果我只想遍历过滤后的结果,这将是一种浪费。

例如:

val map = Map(1 -> "hello", 50 -> "world", 100 -> "hi", 1000 -> "bye")
val filtered = map.filter(x => x._1 < 100)
for(x <- filtered) println(x._2)

我认为使用map.toIterable 没有帮助,因为底层仍然是Map,而filter 是虚拟的。

我不知道map.view 是否具有所需的行为。

我认为map.iterator 会起作用,但这意味着我不能对迭代器进行两次迭代。我想我可以使用map.iterator.filter(x =&gt; x._1 &lt; 100).toList

我可以使用map.map(x =&gt; (x)),但这意味着要遍历 Map 两次。

什么是做我想做的事情的最简单、最惯用的方式,而不是不必要的低效?

【问题讨论】:

  • 如果你想迭代两次并且你不打算用它来构建太昂贵的东西,view 可能是最好的解决方案。如果filter 很昂贵,或者您打算用它构建一些昂贵的东西,iterator 将是最好的。
  • 另外,其他选项可能是编写您自己的方法,从 构建 List (或您喜欢的任何其他结构)映射和谓词。

标签: scala scala-collections


【解决方案1】:

请注意,如果您只想在 for-comprehension 或类似内容中进行迭代(即 flatMapforeachmap),则不会创建中间集合:

for (x <- map if (x._1 < 100)) println(x._2)  // Doesn't create an intermediate Map

这对

map.withFilter(x => x._1 < 100).foreach(x => println(x))

withFilter 是非严格的。

【讨论】:

    【解决方案2】:

    使用collect

    val map = Map(1 -> "hello", 50 -> "world", 100 -> "hi", 1000 -> "bye")
    val filtered : Iterable[String] = map.collect{
     case(x,y) if x<100 => y
    }
    

    只为您提供键满足条件的值

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-27
      • 1970-01-01
      • 2018-02-23
      • 1970-01-01
      • 1970-01-01
      • 2020-03-27
      相关资源
      最近更新 更多