Scala:排序子集最合适的数据结构是什么?

时间:2011-10-17 10:04:27

标签: scala data-structures functional-programming

给定一个大型集合(我们称之为'a')T类型的元素(比如一个Vector或List)和一个评估函数'f'(比如说,(T)=> Double)我想从'a'派生一个结果集合'b',其中包含'a'的N个元素,这些元素在f下具有最高值。集合'a'可能包含重复项。它没有排序。

可能暂时搁置并行化(map / reduce等)的问题,用于编译结果集合'b'的适当的Scala数据结构是什么?感谢您的任何指示/想法。

注意:

(1)我想我的用例可以最简洁地表达为

val a = Vector( 9,2,6,1,7,5,2,6,9 ) // just an example
val f : (Int)=>Double = (n)=>n      // evaluation function
val b = a.sortBy( f ).take( N )     // sort, then clip

除了我不想对整个集合进行排序。

(2)一个选项可能是对“a”的迭代,它使用“手动”大小边界填充TreeSet(拒绝任何比集合中最差项更糟糕的东西,不要让集合增长超过N)。但是,我想保留结果集中原始集中存在的重复项,因此这可能不起作用。

(3)如果排序的多集是正确的数据结构,是否有Scala实现?或者二进制排序的Vector或Array,如果结果集相当小?

1 个答案:

答案 0 :(得分:5)

您可以使用优先级队列:

def firstK[A](xs: Seq[A], k: Int)(implicit ord: Ordering[A]) = {
  val q = new scala.collection.mutable.PriorityQueue[A]()(ord.reverse)
  val (before, after) = xs.splitAt(k)
  q ++= before
  after.foreach(x => q += ord.max(x, q.dequeue))
  q.dequeueAll
}

我们用第一个k元素填充队列,然后将每个附加元素与队列的头部进行比较,并根据需要进行交换。这按预期工作并保留重复:

scala> firstK(Vector(9, 2, 6, 1, 7, 5, 2, 6, 9), 4)
res14: scala.collection.mutable.Buffer[Int] = ArrayBuffer(6, 7, 9, 9)

并没有对完整列表进行排序。我在这个实现中有一个Ordering,但是对它进行调整以使用评估函数将是非常简单的。