Где LINQ в HashSet против списка - PullRequest
1 голос
/ 16 мая 2019

Мне нужно посчитать элементы списка / набора, имеющие свойство с заданным значением. Список огромен, и мне нужна производительность как можно лучше. Должен ли я использовать список или набор (при наличии уникальных элементов)? Есть ли более быстрый способ?

int counter = myList.Where(x => x.A == myValue || x.B == myValue).Count()

Это уже внутри AsParallel().ForAll() для другого огромного списка. И нет, я не могу это изменить.

Редактировать

Я уже видел этот вопрос , и он определенно не решает мою проблему, меня интересуют различия в (P) LINQ-запросах.

1 Ответ

3 голосов
/ 16 мая 2019

Если вы просматриваете коллекцию целиком, обход всего списка, скорее всего, даст лучшую производительность, чем обход всего набора, потому что элементы списка расположены в памяти (при условии, что вы используете List<T>, а не связанный список).

Если вы выполняете тысячи таких запросов для одних и тех же данных в myList, вы можете повысить производительность, построив три справочные таблицы - для x.A, x.B и для общего значения, когда x.A == x.B:

var countByA = myList
    .GroupBy(x => x.A)
    .ToDictionary(g => g.Key, g => g.Count());
var countByB = myList
    .GroupBy(x => x.B)
    .ToDictionary(g => g.Key, g => g.Count());
var countByAandB = myList
    .Where(x => x.A == x.B)
    .GroupBy(x => x.A)
    .ToDictionary(g => g.Key, g => g.Count());

Теперь ваш запрос может быть преобразован в три просмотра с использованием принципа включения-исключения :

countByA.TryGetValue(myValue, out var counterA);
countByB.TryGetValue(myValue, out var counterB);
countByAandB.TryGetValue(myValue, out var counterAandB);
int counter = counterA + counterB - counterAandB;
...