2016-07-06 4 views
1

ストリーム(または要素の長いリスト、数千または数百万になる可能性があります)を持っています。グループの平均。効率的な方法で最初のN個の結果をグループ化、並べ替え、返す

{groupId: 1, value: 10}, {groupId: 2, value: 4}, {groupId: 1: value: 2} 

とフォームグループ:

{groupId: 1, average: 6}, {groupId: 2: average} 

明らかにナイーブな溶液は、グループを反復平均でソートグループ及び第24グループを返すことである形態である項目がそう。何百万ものアイテムを扱うことができる高性能ソリューションのアイディアですか?

+1

グループを平均でソートする場合は、リスト全体を反復処理する方法はありません。しかし、 "何百万"でも、これは大きな問題ではありません。 –

+0

Hmm。あなたはそれがどのような種類のデータであるかは分かりませんでした。おそらくApache SparkやApache Stormのようなマイクロバッチ処理アプリを使用することができます。 –

+0

@CaptainFogettiこのデータはLuceneインデックスに由来しています。私はユースケースでLuceneコレクタを実装しようとしています。 – agori

答えて

1

リスト全体をエスケープして、特定のグループのすべてのメンバーを取得することはできません。あなたはその平均値で利用できる各グループを持っていたら、次の操作を実行できます。

  1. は、ベクター/配列にN最初のグループを取ります。
  2. ヒープの先頭が最大平均のグループになるように、その配列からヒープを作成します。残りの各群について
  3. 、ヒープの最上部と比較:
    • 現在のグループがヒープの最上部よりも大きい場合、それが小さい場合
    • それを捨てるの上部をポップあなたは、ヒープ内のすべてのN最初基を有していても終わりに、現在のグループ

をヒープと挿入します。ヒープソートの最後のステップを適用し、取得したコンテナーを逆にすることで、ヒープを最大ヒープにすることができます。

全体的な複雑:Kは、総グループ数とNは、上記定義される)

O(N +(KN)の.ln(N)+ N.ln (N) = O(N + K.ln(N))

  • 用語Nは、最初のNグループを取得し、最初の最大ヒープを作成することに由来します。
  • 用語(K-N)の.ln(N)(現在のグループを挿入/トップを削除)(最もKで - Nそれらの)操作のペアから来ます。
  • 最後の用語(N.ln(N))は、最終的なヒープのソート用です。
+0

ありがとうございました。これは、Solrがグループ化された結果を並べ替えるためにやっていることですが、平均の代わりにmax関数を使用しています。これらの並べ替え(最初のN要素の並べ替え)がアルゴリズムフィールドに名前を持っているかどうか知っていますか? – agori

+0

@agori私が知っているわけではありませんが、この問題はよく知られています。 IIRCの「コーディング・インタビューのクラッキング」で見つけることができる優れたソリューションもあります。 – Rerito

+0

私はGuavaによって実装された優先度キューを使用しました: 'MinMaxPriorityQueue.orderedBy(new MyComparator()).maximumSize(groupOffset + this.topNGroups).create();' – agori

1

グループごとに2つの値(そのグループとカウンタの合計値)を保持してください。最後に、このグループの平均を得るためにカウンターで合計を割ります。

グループが限られているため情報を保持できません。いずれかのグループがある時点でリーダーになる可能性があるからです。

関連する問題