これは、受け入れられた答えに基づいています。問題は、挿入と取得の両方にO(log(N))SortedDictionary
のコストがかかるため、反復的な構築が遅いことです。
ヒストグラムが蓄積されているときにヒストグラムを表示する必要がない場合は、これを回避できます。
私の変更は法線Dictionary
を使用し、最後にそれを。にソートするだけSortedList
です。
サンプルサイズが1,000万アイテムの場合、このバージョンは(私のマシンでは)約11倍高速ですが、GCが起動するまでのメモリ使用量がわずかに高くなります(約10%の追加メモリ)。
//generate a random sample
Random r = new Random();
var items = Enumerable
.Range(1, 10_000_000)
.Select( _ => (uint)r.Next(100_000))
.ToList();
//build the histogram using a normal dictionary with O(1) lookups and insertions.
var tempHistogram = new Dictionary<uint, int>();
foreach (uint item in items)
{
if (tempHistogram.ContainsKey(item))
{
tempHistogram[item]++;
}
else
{
tempHistogram[item] = 1;
}
}
//Sort it once. SortedList conveniently has a ctor that takes a dictionary.
var sortedHistogram = new SortedList<uint, int>(tempHistogram);
foreach (KeyValuePair<uint, int> pair in sortedHistogram.Take(100))
{
Console.WriteLine("{0} occurred {1} times", pair.Key, pair.Value);
}
非常に大きなサンプル(使用可能なメモリよりも大きい)の場合、この問題を解決する驚くべき確率的アルゴリズムがあります。また、データのストリーミング
にも非常に適しています。「分位スケッチ」を探します。これがApacheFoundationからの実装です:https ://datasketches.apache.org/