Scala:通过可变大小的批次对迭代器进行功能替换

时间:2012-11-23 08:38:13

标签: scala cassandra hector

我正在使用Scala从我们的列商店Cassandra中读取列。每列包含许多条目n,其中n可以在10到20之间。我们读取一批条目,即一次1000条,并且必须从条目创建列;每个条目都附有一个ID,我们可以用它来分组。

目前我们使用迭代器来查看批处理中的条目,并通过比较当前和以前的ID来查明我们是否进入了新列,并且我们阅读了许多批次,直到我们完成。我们需要在每次批处理迭代结束时存储一个部分列,因为列的其余部分将在下一批中。我在下面放了一些伪代码来演示我们目前使用的基本算法。

怎么能以功能的方式做到这一点?(如果n是常数,这将是一个简单的问题,因为我们可以适当地设置批量大小。)

伪代码:

val resultBuffer // collects all columns
val columnBuffer // collects entries for current column
var currentId    // id of current column

while(batchIterator.hasNext){
     val batch = batchIterator.getNext
     val entryIterator = batch.entries.iterator

     while(entryIterator.hasNext){
           val entry = entryIterator.next
            if(entry.id != currentId) {
               currentId = entry.id  
               resultBuffer += columnBuilder(columnBuffer)
               columnBuffer.removeAll
               columnBuffer += entry
            } else {
                columnBuffer += entry
            } 
     }
}

1 个答案:

答案 0 :(得分:1)

这是一个更实用的实现的草图,它使用滑动来对入口迭代器中的条目进行分组:

val resultBuffer // collects all columns

batchIterator.foreach(batch => {
  val buffer = 
    batch.entries.sliding(2).foldLeft(new ColumnBuffer){(buffer, (curr, next)) =>
      if (curr.id != next.id) {
        resultBuffer += columnBuilder(buffer :+ entry /* Append entry to buffer */)
        new ColumnBuffer
      } else
        buffer += entry /* Return buffer with entry added */
    }

  if (buffer.nonEmpty) resultBuffer += columnBuilder(buffer)
}

这里,唯一的对象是" global"因此必须是可变的是resultBuffer。我们甚至可以通过将其作为内部foldLeft中的另一个累加器并将外部foreach替换为另一个foldLeft来摆脱它。

如果运行时效率对您的代码至关重要,那么您应该对各种可能的实现进行基准测试,以便在功能和性能之间找到一个很好的平衡。


编辑1:修复了草图中的错误,即buffer中存储的最后一个条目序列未添加到resultBuffer。该错误已存在于OP的代码中。


编辑2:(解决ChucK的评论)

curr会将值entries(0)带到entries(entries.size() - 2),也就是说,不会处理最后一个元素。解决这个问题的一种方法是在迭代器中附加一个虚拟元素,例如

(batch.entries ++ List(dummy)).sliding(2).foldLeft ...

batch.entries为空时,这不是很好,更重要的是赢了,因为sliding(2)然后生成单个窗口{ {1}}。另一种解决方案是将List(dummy)包含在内部next的累加器中,并在foldLeft终止后处理它。我还没有解决这个问题,但看起来好像这会使解决方案更具吸引力。