【问题标题】:Scala: what is the most appropriate data structure for sorted subsets?Scala:排序子集最合适的数据结构是什么?
【发布时间】:2011-10-17 10:04:26
【问题描述】:

给定一个 T 类型(例如 Vector 或 List)元素的大型集合(我们称之为“a”)和评估函数“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 实现?或者二进制排序的向量或数组,如果结果集相当小?

【问题讨论】:

  • 集合应该针对哪些操作进行优化?
  • @Jesper 用于集合'b':O(logN) 插入,O(1) 最后和第一个元素,O(1) 大小。我想带有二进制排序的 Vector 包装器可能会解决问题,因为我希望结果集相对较小(可能 N=100 个元素)。

标签: scala data-structures functional-programming


【解决方案1】:

您可以使用优先级队列:

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,但调整它以使用评估函数将非常简单。

【讨论】:

  • 这很优雅。不过,我最终修改了与您的代码相关的两个方面:而不是 xs.splitAt() 我现在获取一个迭代器并分两个阶段遍历它(类似于您的之前和之后);否则,我在为大型 Iterables 分配内存时遇到了问题。然后我使用 q.head 代替 q.dequeue 首先测试是否需要出队,这给了我一点加速(> 2x)。谢谢!
  • 我对最后一行做了一些小改动,这可能会带来更多的改进。您不需要对堆进行排序,我只将sorted(ord) 放在最后,因为——令我惊讶的是,显然against the specification——q.iterator 等的输出没有被排序。不过,q.dequeueAll 按预期工作。
  • .dequeueAll 更好。我也花了一段时间才意识到 .iterator、.toList 和 .toString 所承诺的顺序并不是你实际得到的。我会提交一张票。
  • iterator 的文档不正确且不是最新的。迭代器不应该遵守任何顺序。
  • @axel22 对,我猜是你已经对这张票发表了评论。 :-) 无论如何,这是票,仅供参考。 issues.scala-lang.org/browse/SI-5085
猜你喜欢
  • 1970-01-01
  • 2016-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-27
  • 2016-11-10
  • 2012-12-29
  • 1970-01-01
相关资源
最近更新 更多