generazione istogramma semplice dei dati di interi in C #
Domanda
Come parte di un banco di prova che sto costruendo, sto cercando una semplice classe per calcolare un istogramma dei valori interi (numero di iterazioni adottate per un algoritmo per risolvere un problema). La risposta dovrebbe essere chiamato qualcosa come questo:
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] );
}
Sono rimasto sorpreso un po 'di googling non si presentò una soluzione pulita, ma forse non ho la ricerca per le cose giuste. C'è una soluzione generica là fuori o vale la pena di rotazione mia?
Soluzione
Si potrebbe utilizzare 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);
}
Questo lascerà fuori bidoni vuoti, anche se
Altri suggerimenti
In base a suggerimento di BastardSaint mi si avvicinò con un involucro ordinata e abbastanza generica:
public class Histogram<TVal> : SortedDictionary<TVal, uint>
{
public void IncrementCount(TVal binToIncrement)
{
if (ContainsKey(binToIncrement))
{
this[binToIncrement]++;
}
else
{
Add(binToIncrement, 1);
}
}
}
Così ora posso fare:
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);
}
ho messo un po 'per capire come renderlo generico (per cominciare ho appena calpestato il costruttore SortedDictionary
che significava che si poteva utilizzare solo per le chiavi uint
).
È possibile utilizzare 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);
});