如何在不创建中间 Seq 的情况下对可迭代对象进行排序?



我有一张String -> Foo地图,我想通过Foo.priority获得Foos的排序集合:

fooMap.collect { case (k, f) if k.startWith("F") => f }.toSeq.sortBy(_.priority)

如何避免中间toSeq?我可以创建一个新集合并通过排序插入吗?也许像这样:

fooMap.collect { case (k, f) if k.startWith("F") => f }.to[Seq](orderedCanBuildFrom) //does not work

您无法直接对Iterable进行排序,并且您描述的插入排序对于大型集合来说会非常慢。

最好的选择可能是转换为Array并使用 scala.util.sort 包,该包提供Array的就地排序。

既然你说你的内存和延迟很紧,试试这个

fooMap.view.filter(_._1.startsWith("F")).map(_._2).toSeq.sortBy(_.priority)

否则,请考虑购买更多内存和/或速度:)。

对于 Scala 2.12 及更低版本,我使用自定义的 CanBuildFrom 来允许 map/collection 转换为不同的集合类型。scala.collection.breakOut自动执行此操作:

import scala.collection.breakOut
fooMap.collect[Foo, Seq[Foo]]  { 
case (k, f) if k.startWith("F") => f
}(breakOut).sortBy(_.priority)

对于 Scala 2.13及更高版本,由于CanBuildFrombreakOut不再可用,并且View更可靠,我会使用 @volty-de-qua 回答中所述的观点,因为只有从 2.13 开始collection.Views have been vastly simplified and should now work reliably.

最新更新