Поиск, если значение существует в списке объектов, используя Linq


228

Скажем, у меня есть класс, у Customerкоторого есть свойство FirstName. Тогда у меня есть List<Customer>.

Можно ли использовать LINQ, чтобы узнать, есть ли в списке клиент с Firstname = 'John'одним оператором ... как?

Ответы:


459

LINQ определяет метод расширения, который идеально подходит для решения именно этой проблемы:

using System.Linq;
...
    bool has = list.Any(cus => cus.FirstName == "John");

убедитесь, что вы ссылаетесь на System.Core.dll, там живет LINQ.


24
Любое хорошо, интересно, сколько разработчиков используют Count, когда они должны использовать Any?
RichardOD

12
Вы также можете выполнить поиск без учета регистра: cus => cus.FirstName.Equals ("John", StringComparison.CurrentCultureIgnoreCase)
jmservera

1
Я знаю, что это старый вопрос, но почему мы не используем метод Exists? Видя, как это сделано, чтобы увидеть, существуют ли вещи.
Blackunknown

6
Потому что не во всех коллекциях есть Exists, и оно не принимает лямбда-выражения, а скорее объект, который мы ищем сам.
Зволков

1
@zvolkov, любые идеи, почему мой резарпер предлагает использовать bool has = list.All (cus => cus.FirstName! = "John"); Это более оптимально?
Гулу

105

Ответ Зволкова является идеальным, чтобы выяснить, есть ли такой клиент. Если вам нужно использовать клиента впоследствии, вы можете сделать:

Customer customer = list.FirstOrDefault(cus => cus.FirstName == "John");
if (customer != null)
{
    // Use customer
}

Я знаю, что это не то, что вы спрашивали, но я подумал, что предпочитаю последующий вопрос :) (Конечно, это находит только первого такого клиента ..., чтобы найти их всех, просто используйте нормальное whereпредложение.)


7
Я хотел бы отметить, что вы могли бы оценить, что сделали это позже, когда дело доходит до отладки, если вам вдруг стало любопытно, какой именно клиент соответствует этим критериям.
MQP

1
Просто поднимите этот ответ, потому что мне нравится, как сообщество SO делает дополнительный шаг, чтобы добавить еще больше к вопросу / ответу.
barneymc

1
спасибо, это помогло мне, но иногда я просто хочу получить boolрезультат, так что в этом случае .Anyили .FindIndexиспользуется здесь, что быстро ?
Shaijut

1
@stom: Они оба O (N), в основном ... это просто линейные поиски.
Джон Скит

натыкаясь на это. Мне нравится, как вы используете синтаксис list.FirstOrDefault вместо того, чтобы делать list.Where (). FirstOrDefault.
GunWanderer

25

Один из вариантов ответа на вопрос (как найти клиента, который может иметь любое количество имен):

List<string> names = new List<string>{ "John", "Max", "Pete" };
bool has = customers.Any(cus => names.Contains(cus.FirstName));

или получить клиента из csv аналогичного списка

string input = "John,Max,Pete";
List<string> names = input.Split(',').ToList();
customer = customers.FirstOrDefault(cus => names.Contains(cus.FirstName));

10

Используя Linq, у вас есть много возможностей, в том числе без лямбд:

//assuming list is a List<Customer> or something queryable...
var hasJohn = (from customer in list
         where customer.FirstName == "John"
         select customer).Any();

5
customerList.Any(x=>x.Firstname == "John")

Это не отвечает на вопрос «если» такая запись существует; он просто перечисляет значения, если они существуют. Дополнительный шаг необходим, чтобы определить, является ли это перечисление непустым.
Джейсон

Затем измените «Куда-нибудь». Наверное, более философски для меня. Мне редко нужно знать, не заботясь о том, кто они. @jmservera: ты был прав. Я отказался от LINQ некоторое время назад и теперь использую исключительно Lambda.
Крис Брэндсма

Я не хочу быть педантичным, когда говорю, что использование лямбда-вызовов по-прежнему технически использует LINQ. (В частности, вы используете LINQ-to-Objects.) Вы просто используете вызовы методов, а не ключевые слова языка.
Иуда Габриэль Химанго

Чем этот ответ отличается от ответа Золькова?
dotnetN00b

4

Техника, которую я использовал перед открытием .Any():

var hasJohn = (from customer in list
      where customer.FirstName == "John"
      select customer).FirstOrDefault() != null;

3
List<Customer> list = ...;
Customer john = list.SingleOrDefault(customer => customer.Firstname == "John");

Джон будет нулевым, если не существует ни одного клиента с именем «Джон».


2
Это создаст исключение, если более одного клиента зовут Джон.
Джон Скит

1
Спасибо за комментарий. Я оставлю ответ как частично правильный пример.
M4N

Это все еще действует в сценарии, когда вы уверены, что есть 1, и вы хотите, чтобы было сгенерировано исключение, если их больше одного, поэтому я думаю, это хорошо, что вы не удалили его.
RichardOD

1

Другая возможность

if (list.Count(customer => customer.Firstname == "John") > 0) {
 //bla
}

4
В этом сценарии предпочтительнее использовать Any.
RichardOD

1

Попробуйте это, я надеюсь, это поможет вам.

 if (lstCustumers.Any(cus => cus.Firstname == "John"))
 {
     //TODO CODE
 }

4
Это так же, как принятый ответ более 8 лет назад. Пожалуйста, убедитесь, что ваш ответ уникален среди всех ответов.
Tony_Henrich
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.