我有一张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及更高版本,由于CanBuildFrom
和breakOut
不再可用,并且View
更可靠,我会使用 @volty-de-qua 回答中所述的观点,因为只有从 2.13 开始collection.Views have been vastly simplified and should now work reliably.