Question

Dans le cadre d'un banc d'essai je construis, je suis à la recherche d'une classe simple pour calculer un histogramme des valeurs entières (nombre d'itérations prises pour un algorithme pour résoudre un problème). La réponse devrait être appelé quelque chose comme ceci:

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] );
}

Je suis un peu surpris de googler ne se sont pas une solution propre, mais peut-être que je ne cherchais pas pour les bonnes choses. Y at-il une solution générique là-bas ou est-il utile rouler mon?

Était-ce utile?

La solution

Vous pouvez utiliser 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);
}

Cela laissera des bacs vides, bien que

Autres conseils

Basé sur la suggestion de BastardSaint je suis venu avec un emballage soigné et assez générique:

public class Histogram<TVal> : SortedDictionary<TVal, uint>
{
    public void IncrementCount(TVal binToIncrement)
    {
        if (ContainsKey(binToIncrement))
        {
            this[binToIncrement]++;
        }
        else
        {
            Add(binToIncrement, 1);
        }
    }
}

Alors maintenant, je peux le faire:

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);
}

Il m'a fallu un certain temps pour trouver comment rendre générique (pour commencer que je viens de l'emportaient sur le constructeur de SortedDictionary qui signifiait que vous ne pouviez l'utiliser pour les clés de uint).

Vous pouvez utiliser 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);
    });
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top