Einfache Histogrammerzeugung von ganzzahligen Daten in C #
Frage
Im Rahmen eines Prüfstandes Ich baue, ich bin auf der Suche nach einer einfachen Klasse ein Histogramm der Integer-Werte (Anzahl der Iterationen für einen Algorithmus genommen ein Problem zu lösen) zu berechnen. Die Antwort sollte wie folgt aufgerufen werden:
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] );
}
Ich war ein bisschen googeln überrascht hat keine saubere Lösung auftauchen, aber vielleicht habe ich nicht für die richtigen Dinge suchen. Gibt es eine generische Lösung gibt, oder ist es meine eigenen Wert rollen?
Lösung
Sie könnten verwenden 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);
}
Dies wird leeren Behälter auslassen, obwohl
Andere Tipps
Basierend auf BastardSaint Vorschlag kam ich mit einem ordentlichen und ziemlich allgemein Wrapper:
public class Histogram<TVal> : SortedDictionary<TVal, uint>
{
public void IncrementCount(TVal binToIncrement)
{
if (ContainsKey(binToIncrement))
{
this[binToIncrement]++;
}
else
{
Add(binToIncrement, 1);
}
}
}
So, jetzt kann ich tun:
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);
}
dauerte eine Weile, um herauszufinden, wie es generische zu machen (beginnen ich overrode nur den SortedDictionary
Konstruktor was bedeutete, dass man es nur für uint
Schlüssel verwenden könnte).
Sie können Linq verwenden:
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);
});