Найти в массиве double дубликаты и их количество

Есть большой list double MasNow, в нем очень много элементов, хочу построить график распределения для каждого элемента т.е. график элемент/количество его в массиве:

List<double> checkDis = new List<double>();

 foreach(var ddr in MasNow)
 {
     if (checkDis.Contains(ddr))
     {

     }
     checkDis.Add(ddr);
 }

Думал в таком направлении. Элементы т.е. значения в пределах 20-80.


Ответы (1 шт):

Автор решения: Faraday

Можете попробовать вот так:

List<double> list = new List<double>() { ... };
Dictionary<double, int> duplicates = new Dictionary<double, int>();

foreach(var ddr in list)
{
    if (duplicates.ContainsKey(ddr))
    {
        duplicates[ddr]++;
    }
    else
    {
        duplicates.Add(ddr, 1);
    }
}

Суть в том, что при прохождении по списку вы будете добавлять элемент в словарь. Перед добавлением осуществляется проверка на наличие такого же значения в этом словаре. Если оно существует, мы увеличиваем счетчик количество нахождений этого числа. В ином случае, вы добавляем элемент в словарь со значением 1 в качество встречаемого количества, т.к. мы только что увидели это значение первый раз.

Так же это можно реализовать через linq. Вот как можно получить тот же словарь путём использования linq:

var counts = MasNow.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count());

UPD:* Почему такое подход эффективнее? Как уже сказали в комментариях (@CrazyElf), операция Contains для списка (List) имеет сложность O(n), где n - это количество элементов в списке. Это означает, что в худшем случае для поиска элемента в списке потребуется пройти через все его элементы.

Операция ContainsKey для словаря (Dictionary<TKey, TValue>) имеет сложность O(1), что означает, что время, необходимое для проверки наличия ключа в словаре, не зависит от размера словаря.

UPD:** Как снова дополнил один из комментаторов, так же можно использовать метод TryGetValue класса Dictionary, что позволит сократить количество операций. В таком случае код будет выглядеть следующим образом:

List<double> list = new List<double>() { 1, 2, 2, 3, 1, 4, 6, 2 };
Dictionary<double, int> duplicates = new Dictionary<double, int>();

foreach(var ddr in list)
{
    duplicates.TryGetValue(ddr, out int count);
    duplicates[ddr] = count + 1;
}
→ Ссылка