Wyszukiwanie, czy wartość istnieje na liście obiektów za pomocą Linq

228

Powiedz, że mam klasę, Customerktóra ma właściwość FirstName. Więc mam List<Customer>.

Czy można użyć LINQ do sprawdzenia, czy lista ma klienta Firstname = 'John'w jednym wyciągu ... jak?

Tony_Henrich
źródło

Odpowiedzi:

459

LINQ definiuje metodę rozszerzenia, która jest idealna do rozwiązania tego konkretnego problemu:

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

upewnij się, że odwołujesz się do System.Core.dll, tam mieszka LINQ.

zvolkov
źródło
24
Wszystko jest dobre, zastanawiam się, ilu programistów używa Count, kiedy powinno używać Any?
RichardOD
12
Możesz także wyszukiwać bez rozróżniania wielkości liter: cus => cus.FirstName.Equals ("John", StringComparison.CurrentCultureIgnoreCase)
jmservera
1
Wiem, że to stare pytanie, ale dlaczego nie korzystamy z metody Exists? Widząc, jak się robi, aby sprawdzić, czy coś istnieje.
Blackunknown
6
Ponieważ nie wszystkie kolekcje mają Istnienie i nie przyjmuje wyrażenia lambda, a raczej obiekt, którego szukamy.
zvolkov
1
@zvolkov, Wszelkie pomysły, dlaczego mój resharper sugeruje używanie bool has = list.All (cus => cus.FirstName! = "John"); Czy to jest bardziej optymalne?
Gullu,
105

Odpowiedź Zvolkova jest idealna, aby dowiedzieć się, czy istnieje taki klient. Jeśli chcesz później skorzystać z klienta, możesz:

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

Wiem, że nie o to pytasz, ale pomyślałem, że uprzedzę kolejne pytanie :) (Oczywiście, to znajdzie tylko pierwszego takiego klienta ... aby znaleźć je wszystkie, po prostu użyj normalna whereklauzula).

Jon Skeet
źródło
7
Zwracam uwagę, że możesz docenić to, że zrobiłeś to później, jeśli chodzi o debugowanie, jeśli nagle zorientujesz się, który klient spełnia kryteria.
mqp
1
Po prostu podniosłem tę odpowiedź o jeden, bo uwielbiam sposób, w jaki społeczność SO robi dodatkowy krok, aby dodać jeszcze więcej do pytania / odpowiedzi.
barneymc
1
dzięki, pomogło mi to, ale czasami po prostu chcę uzyskać boolwynik, więc w takim przypadku .Anylub .FindIndexjest używany tutaj, co jest szybkie ?
shaijut
1
@stom: Oboje są O (N), w zasadzie ... są to tylko wyszukiwania liniowe.
Jon Skeet
wysadzić to w powietrze. Podoba mi się sposób, w jaki używasz składni list.FirstOrDefault zamiast tworzenia list.Where (). FirstOrDefault.
GunWanderer
25

Jedna z opcji dla następujących pytań (jak znaleźć klienta, który może mieć dowolną liczbę imion):

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

lub w celu pobrania klienta z csv podobnej listy

string input = "John,Max,Pete";
List<string> names = input.Split(',').ToList();
customer = customers.FirstOrDefault(cus => names.Contains(cus.FirstName));
Mike Sackton
źródło
10

Korzystając z Linq masz wiele możliwości, tutaj bez użycia lambdas:

//assuming list is a List<Customer> or something queryable...
var hasJohn = (from customer in list
         where customer.FirstName == "John"
         select customer).Any();
jmservera
źródło
5
customerList.Any(x=>x.Firstname == "John")
Chris Brandsma
źródło
To nie odpowiada na pytanie „jeśli” taki wpis istnieje; po prostu wylicza wartości, jeśli istnieją. Potrzebny jest dodatkowy krok, aby ustalić, czy to wyliczenie nie jest puste.
jason
Następnie zmień opcję Where to Any. Prawdopodobnie bardziej filozoficzny dla mnie. Rzadko muszę wiedzieć, czy nie dbając o to, które to są. @jmservera: miałeś rację. Dawno zrezygnowałem z LINQ i teraz używam wyłącznie Lambdy.
Chris Brandsma
Nie chcę być pedantyczny, kiedy mówię, że używanie połączeń lambda nadal technicznie korzysta z LINQ. (W szczególności korzystasz z LINQ-to-Objects.) Po prostu używasz wywołań metod, a nie słów kluczowych w języku.
Judah Gabriel Himango
Czym różni się ta odpowiedź od Zvolkova?
dotnetN00b
4

Technika, której użyłem przed odkryciem .Any():

var hasJohn = (from customer in list
      where customer.FirstName == "John"
      select customer).FirstOrDefault() != null;
Ian Boyd
źródło
3
List<Customer> list = ...;
Customer john = list.SingleOrDefault(customer => customer.Firstname == "John");

John będzie zerowy, jeśli nie będzie klienta o imieniu „John”.

M4N
źródło
2
Spowoduje to wyjątek, jeśli więcej niż jeden klient nazywa się John.
Jon Skeet
1
Dziękuję za komentarz. Pozostawię odpowiedź jako częściowo poprawny przykład.
M4N
Jest to nadal ważne w scenariuszu, gdy masz pewność, że jest 1 i chcesz, aby wyjątek został zgłoszony, jeśli jest więcej niż jeden, więc myślę, że dobrze jest, że go nie usunąłeś.
RichardOD
1

Inna możliwość

if (list.Count(customer => customer.Firstname == "John") > 0) {
 //bla
}
Krassi
źródło
4
W tym scenariuszu lepiej jest użyć dowolnego.
RichardOD
1

Spróbuj tego, mam nadzieję, że ci to pomoże.

 if (lstCustumers.Any(cus => cus.Firstname == "John"))
 {
     //TODO CODE
 }
Fabio Stratotti
źródło
4
To to samo, co przyjęta odpowiedź sprzed ponad 8 lat. Upewnij się, że Twoja odpowiedź jest unikalna wśród wszystkich odpowiedzi.
Tony_Henrich