Страницы

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

пятница, 14 февраля 2020 г.

Как написать Linq запрос к коллекции, где значение коллекции- свой класс?

#c_sharp #linq


Есть коллекция Dictionary products = new Dictionary();
Одно из свойств класса MyClass - Group (группа товара), тип string. Мне нужно узнать
есть хоть один элемент в коллекции, у которого свойство Group = "Мясо", к примеру.

if (products.Where(x=>x.Value?.Group == "Мясо").Count()>0)


Так корректно? Спасибо. Мне важно, чтобы максимально быстро была проверка
    


Ответы

Ответ 1



Чуть подробнее поясню ответ, который вам дали в комментариях. Ваш запрос неоптимален. У вас сначала отбираются элементы через Where, потом считается их число. И только потом проверяется на ноль. Представьте, что вы решили сделать эту проверку перебором. При этом вы сначала отобрали элементы с "мясо" в новую переменную (заняли память, съели время). Потом другим циклом посчитали количество элементов и записали в переменную (заняли память, сделали второй проход по циклу) и потом сравнили. Вы же так не стали бы делать, верно? Вот и мы давайте не будем делать. Можно объединить Where и Count: if (products.Count(x=>x.Value?.Group == "Мясо")>0) Уже стало лучше. Однако стоит ли перебирать весь массив или достаточно найти хотя бы один элемент и как только нашли - сразу выйти из цикла? [__DynamicallyInvokable] public static bool Any(this IEnumerable source, Func predicate) { if (source == null) throw Error.ArgumentNull(nameof (source)); if (predicate == null) throw Error.ArgumentNull(nameof (predicate)); foreach (TSource source1 in source) { if (predicate(source1)) return true; } return false; } Заменяем Count на Any: if (products.Any(x=>x.Value?.Group == "Мясо")) Всё, в пределах linq больше оптимизировать некуда. Отдельное замечание нужно сделать по поводу того, что могла бы первая оптимизация сделана самим компилятором при условии, что у вас был бы IQueryable, а не IEnumerable, но я не уверен, что компилятор бы смог заменить Count > 0 на Any - он бы честно посчитал. Стоит ли заменять linq на цикл? Не стоит - я показал, что под капотом у Any тот же самый цикл. А выглядит такая linq конструкция короче и семантичнее, а потому понятнее при чтении.

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

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