Оптимизация эффективности linq - PullRequest
0 голосов
/ 05 июля 2018

Я получил этот linq:

return ngrms.GroupBy(x => x)
            .Select(s => new { Text = s.Key, Count = s.Count() })    
            .Where(x => x.Count > minCount)
            .OrderByDescending(x => x.Count)
            .ToDictionary(g => g.Text, g => g.Count);

ngrms - это IEnumerable<String>

Есть ли способ, которым я могу оптимизировать этот код? Мне все равно, если мне придется переписать весь код и открыть для всех низкоуровневых настроек.

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Если вы реализуете Dictionary, который можно увеличивать (эмулируя мультимножество или пакет), то вы можете увеличить скорость примерно в 3 раза быстрее, чем LINQ, но разница невелика, если у вас не много ngrms. В списке из 10 миллионов, содержащем около 100 уникальных значений, код LINQ все еще занимает меньше секунды на моем ПК. Если ваш код LINQ занимает время 1, foreach с Dictionary<string,int> - 0,85, а этот код - 0,32.

Вот класс для создания обновляемого значения в Dictionary:

public class Ref<T> {
    public T val { get; set; }
    public Ref(T firstVal) => val = firstVal;
    public static implicit operator T(Ref<T> rt) => rt.val;
}

(Если бы C # позволял operator ref T, вы могли бы вернуть ref свойству val и почти обработать Ref<T>, как если бы это было lvalue типа T.)

Теперь вы можете сосчитать вхождения строк в Dictionary<string,Ref<int>> только с одним поиском на строку:

var dictCounts = new Dictionary<string, Ref<int>>();
foreach (var s in ngrms) {
    if (dictCounts.TryGetValue(s, out var refn))
        ++refn.val;
    else
        dictCounts.Add(s, new Ref<int>(1));
}

Наконец, вы можете вычислить ответ, отфильтровав значения, которые вы хотите сохранить:

var ans = dictCounts.Where(kvp => kvp.Value > minCount).ToDictionary(kvp => kvp.Key, kvp => kvp.Value.val);
0 голосов
/ 05 июля 2018

Исходя из вашего запроса linq, вы можете переписать код с помощью простого цикла foreach для повышения производительности, как показано ниже. Для выполнения требуется o(n) сложность времени:

Dictionary<string, int> dict = new Dictionary<string, int>();
foreach(var s in ngrms)
{
    if (dict.ContainsKey(s))
        dict[s]++;
    else
        dict.Add(s, 1);
}
return dict.Where(a => a.Value > minCount);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...