Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

Подсчет количества совпадение в списке

#c_sharp #list


Есть список слов. Хочу получить результирующий словарь в котором я бы мог получить
количество одинаковых строк. Т.е. словарь будет содержать {слово;количество совпадений}. 

Данный код делает это, но ооочень медленно. Что я не так сделал, что оно так тормозит

var file = File.ReadAllLines(@"1.txt").ToList();

var result = file
  .Select(str => new { Name = str, Count = file.Count(s => s == str) })
  .Where(obj => obj.Count > 1)
  .Distinct()
  .ToDictionary(obj => obj.Name, obj => obj.Count);

    


Ответы

Ответ 1



Воспользуйтесь словарем. Он обеспечивает быстрый поиск по ключу. В данном случае мы будем проверять существует ли слово в словаре. Если не существует — добавляем его, а счетчик устанавливаем в 1. И если существует — делаем поиск по ключу и увеличиваем счетчик на 1. Главной особенностью словарей, является то, что они имеют уникальные ключи, которые получаются путем извлечения хэш-кода значения. Формируется таблица хэш-кодов, которая обеспечивает быстрый поиск. var dict = new Dictionary(); foreach (var line in File.ReadLines(@"1.txt")){ if (dict.ContainsKey(line)){ dict[line]++; } else { dict.Add(line, 1); } } Как подсказал @VladD По идее, лучше обойтись без материализации списка: ReadLines вместо ReadAllLines. Сложность выполнения вашего кода будет равна O(N^2), а при использовании словаря — O(N).

Ответ 2



Ну да, будет тормозить, у вас квадратичный алгоритм. Вы на каждой итерации перечитываете список заново. Вам поможет GroupBy: File.ReadLines(path) .GroupBy(s => s) .ToDictionary(g => g.Key, g => g.Count()) Если вам нужно выкинуть уникальные строки, нужно немного длиннее: File.ReadLines(path) .GroupBy(s => s) .Select(g => (value: g.Key, count: g.Count())) .Where(t => t.count > 1) .ToDictionary(t => t.value, t => t.count)

Комментариев нет:

Отправить комментарий