作为我正在构建的测试平台的一部分,我正在寻找一个简单的类来计算整数值的直方图(算法解决问题的迭代次数)。答案应该是这样的:
Histogram my_hist = new Histogram();
for( uint i = 0; i < NUMBER_OF_RESULTS; i++ )
{
myHist.AddValue( some_result );
}
for( uint j = 0; j < myHist.NumOfBins; j++ )
{
Console.WriteLine( "{0} occurred {1} times", myHist.BinValues[j], myHist.BinCounts[j] );
}
我很惊讶有点谷歌搜索没有找到一个简洁的解决方案,但也许我没有找到正确的事情。那里有一个通用的解决方案还是值得自己动手?
答案 0 :(得分:14)
您可以使用SortedDictionary
uint[] items = new uint[] {5, 6, 1, 2, 3, 1, 5, 2}; // sample data
SortedDictionary<uint, int> histogram = new SortedDictionary<uint, int>();
foreach (uint item in items) {
if (histogram.ContainsKey(item)) {
histogram[item]++;
} else {
histogram[item] = 1;
}
}
foreach (KeyValuePair<uint, int> pair in histogram) {
Console.WriteLine("{0} occurred {1} times", pair.Key, pair.Value);
}
虽然
,但这会留下空箱子答案 1 :(得分:6)
基于BastardSaint的建议,我提出了一个整洁且相当通用的包装器:
public class Histogram<TVal> : SortedDictionary<TVal, uint>
{
public void IncrementCount(TVal binToIncrement)
{
if (ContainsKey(binToIncrement))
{
this[binToIncrement]++;
}
else
{
Add(binToIncrement, 1);
}
}
}
现在我可以做到:
const uint numOfInputDataPoints = 5;
Histogram<uint> hist = new Histogram<uint>();
// Fill the histogram with data
for (uint i = 0; i < numOfInputDataPoints; i++)
{
// Grab a result from my algorithm
uint numOfIterationsForSolution = MyAlorithm.Run();
// Add the number to the histogram
hist.IncrementCount( numOfIterationsForSolution );
}
// Report the results
foreach (KeyValuePair<uint, uint> histEntry in hist.AsEnumerable())
{
Console.WriteLine("{0} occurred {1} times", histEntry.Key, histEntry.Value);
}
我花了一些时间来研究如何使它成为通用的(首先我只是覆盖了SortedDictionary
构造函数,这意味着你只能将它用于uint
个键)。
答案 2 :(得分:3)
您可以使用Linq:
var items = new[] {5, 6, 1, 2, 3, 1, 5, 2};
items
.GroupBy(i => i)
.Select(g => new {
Item = g.Key,
Count = g.Count()
})
.OrderBy(g => g.Item)
.ToList()
.ForEach(g => {
Console.WriteLine("{0} occurred {1} times", g.Item, g.Count);
});
答案 3 :(得分:0)
此代码提供了数组值的图形表示。
using System;
// ...
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Cyan;
int[] array = { 2, 2, 2 };
PrintHistogram(array);
Console.ForegroundColor = ConsoleColor.Gray;
Console.Write("Press any key to quit . . . ");
Console.ReadKey(true);
}
static void PrintHistogram(int[] array)
{
int largest = 0;
for (int i = 0; i < array.Length; i++)
largest = Math.Max(largest, array[i]);
largest--;
// Bars
while (largest >= 0)
{
for (int i = 0; i < array.Length; i++)
{
if (array[i] > largest)
Console.Write("|\t");
else
Console.Write("\t");
}
largest--;
Console.WriteLine();
}
Console.WriteLine();
// Numbers
for (int i = 0; i < array.Length; i++)
Console.Write(array[i] + "\t");
Console.WriteLine();
}
答案 4 :(得分:0)
我实现了创建直方图的简单扩展方法:
public static IReadOnlyDictionary<T, int> ToHistogram<T>(this IEnumerable<T> enumerable)
=> enumerable.GroupBy(item => item).ToDictionary(grouping => grouping.Key, grouping => grouping.Count());