Избегайте просмотра списка несколько раз с помощью linq, с динамическими условиями (фильтр)

У меня есть список с Article объекты. Параметры для этого объекта:

Категория, описание, статус, класс

Пользователь может фильтровать список с помощью комбинации, которую он хочет. Только Описание, или Категория + Класс, и так далее.

Поэтому, если пользователь выберет критерий, я получу int >= 0, в противном случае я получу -1.

Например, если он хочет фильтровать с Status а также Category, Я получу

FilterCategory = x, FilterDescription = -1, FilterStatus = y, FilterClass = -1

Мой способ фильтрации списка заключается в следующем:

if (FilterCategory != -1)
    list = list.Where(a => a.Category == FilterCategory);
if (FilterDescription != -1)
    list = list.Where(a => a.Description == FilterDescription);
if (FilterStatus != -1)
    list = list.Where(a => a.Status == FilterStatus);
if (FilterClass != -1)
    list = list.Where(a => a.Class == FilterClass);

Таким образом, я должен повторить список 4 раза, это не эффективно с большим количеством элементов. Я бы просмотрел список один раз и проверил 4 условия в уникальном месте. Но я не знаю, как это сделать с определенным условием!= -1.

Спасибо

3 ответа

Решение

Вы можете сделать ОГРОМНЫЙ, где запрос переместит все ваши условия в один Where заметив, что:

if (FilterCategory != -1)
    list = list.Where(a => a.Category == FilterCategory);

эквивалентно:

list = list.Where(a => FilterCategory == -1 || a.Category == FilterCategory);

Тогда запрос:

list = list.Where(a => (FilterCategory == -1 || a.Category == FilterCategory)
                    && (FilterDescription == -1 || a.Description == FilterDescription)
                    && (FilterStatus == -1 || a.Status == FilterStatus)
                    && (FilterClass == -1 || a.Class == FilterClass));

Но я действительно сомневаюсь, что это улучшит ваши показатели перечисления.

Как Юхарр упоминает в комментариях, Linq не будет оценивать вашу .Where сразу после звонка. Только при звонке ToList/ToArray/First/Single/foreach он оценит предложение и автоматически объединит ваши фильтры.

list = list.Where(a => (FilterCategory != -1 || a.Category == FilterCategory) && 
                                       (FilterDescription != -1 || a.Description == FilterDescription) &&
                                       (FilterStatus != -1 || a.Status == FilterStatus) &&
                                       (FilterClass != -1 || a.Class == FilterClass));
Другие вопросы по тегам