这建立在公认的答案之上。问题是SortedDictionary
迭代构建一个很慢,因为插入和检索都花费O(log(N))。
如果您不需要在累积时显示直方图,则可以避免这种情况。
我的修改使用了一个普通的Dictionary
,并且只在最后将它排序为一个SortedList
.
对于 1000 万个项目的样本大小,这个版本大约快 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);
}
对于非常大的样本(大于可用内存),有惊人的概率算法可以解决这个问题。
它们也非常适合流式传输数据。寻找“分位数草图”。这是 Apache 基金会的一个实现:https ://datasketches.apache.org/