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?

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.


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).


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));

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();

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

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;

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”.


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
}

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
 }

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.