Генерация простой гистограммы целочисленных данных в C # - PullRequest
8 голосов
/ 29 мая 2009

Как часть тестового стенда, который я создаю, я ищу простой класс для вычисления гистограммы целочисленных значений (количество итераций, принятых для алгоритма решения проблемы). Ответ должен называться примерно так:

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

Я был удивлен, что поиск в Google не нашел правильного решения, но, возможно, я не искал правильные вещи. Есть ли какое-то общее решение, или оно стоит моего?

Ответы [ 4 ]

14 голосов
/ 29 мая 2009

Вы можете использовать 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);
}

Это оставит пустые корзины, хотя

6 голосов
/ 29 мая 2009

По предложению 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 ключей).

3 голосов
/ 25 июля 2013

Вы можете использовать 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);
    });
0 голосов
/ 18 декабря 2016

Этот код дает графическое представление значений массива.

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();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...