0

私は Scala を使用して、列ストアの Cassandra から列を読み取ります。各列には多数のエントリ n が含まれます。ここで、n は 10 から 20 の間です。エントリのバッチ、つまり一度に 1000 を読み取り、エントリから列を作成する必要があります。各エントリには、グループ化に使用できる ID が添付されています。

現在、イテレータを使用してバッチ内のエントリを調べ、現在の 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
            } 
     }
}
4

1 に答える 1

1

以下は、スライディングを使用して entry-iterator 内のエントリをグループ化する、より機能的な実装のスケッチです。

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)
}

ここで、「グローバル」であり、したがって変更可能でなければならない唯一のオブジェクトは ですresultBufferfoldLeft内部に別のアキュムレータとして含め、外部foreachを別のものに置き換えることで、それを取り除くことさえできfoldLeftます。

コードにとってランタイム効率が重要な場合は、機能性とパフォーマンスの間の適切なトレードオフを見つけるために、さまざまな可能な実装を確実にベンチマークする必要があります。


編集 1:スケッチのエラーを修正しました。つまり、に格納されたエントリの最後のシーケンスが にbuffer追加されませんでしたresultBuffer。エラーは OP のコードに既に存在します。


EDIT 2:(チャックのコメントへの対処)

currつまり、最後の要素は処理されませentries(0)ん。entries(entries.size() - 2)これに対処する 1 つの方法は、イテレータにダミー要素を追加することです。

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

これは良くありません。さらに重要なことに、が空の場合は機能しません。これは、単一の window が生成されるためです。別の解決策は、内部のアキュムレータに含め、 が終了した後に処理することです。私はそれを解決していませんが、それがソリューションの魅力をさらに低下させるように見えます.batch.entriessliding(2)List(dummy)nextfoldLeftfoldLeft

于 2012-11-23T09:06:43.553 に答える