Найти в массиве 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 шт):
Можете попробовать вот так:
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;
}