【发布时间】:2011-11-25 22:16:59
【问题描述】:
试图找到一种有效的方法来获取一个非常大的列表中的前 N 个项目,可能包含重复项。
我首先尝试了排序和切片,这很有效。但这似乎是不必要的。如果您只需要前 20 名成员,则不需要对非常大的列表进行排序。 所以我写了一个递归例程来构建 top-n 列表。这也有效,但比非递归慢得多!
问题:我的第二个例程 (elite2) 比精英慢得多,我如何让它更快?我的代码附在下面。谢谢。
import scala.collection.SeqView
import scala.math.min
object X {
def elite(s: SeqView[Int, List[Int]], k:Int):List[Int] = {
s.sorted.reverse.force.slice(0,min(k,s.size))
}
def elite2(s: SeqView[Int, List[Int]], k:Int, s2:List[Int]=Nil):List[Int] = {
if( k == 0 || s.size == 0) s2.reverse
else {
val m = s.max
val parts = s.force.partition(_==m)
val whole = if( parts._1.size > 1) parts._1.tail:::parts._2 else parts._2
elite2( whole.view, k-1, m::s2 )
}
}
def main(args:Array[String]) = {
val N = 1000000/3
val x = List(N to 1 by -1).flatten.map(x=>List(x,x,x)).flatten.view
println(elite2(x,20))
println(elite(x,20))
}
}
【问题讨论】:
-
注意,如果你想取前n个元素,最好使用
.take(n) -
我对前 n 个元素不感兴趣。对前n感兴趣。所以 { 4,3,2,5,7,1}.take(2) 给出 {4,3}。我想要前 2 个 { 7,5}。
-
我在
elite谈过.slice(0,min(k,s.size)) -
哦,你希望我使用 take 而不是 slice。很好。很抱歉造成混乱。
-
这里stackoverflow.com/q/5674741/312172是一个类似的线程