Cercare se esiste un valore in un elenco di oggetti usando Linq


228

Di 'che ho una lezione Customer che ha una proprietà FirstName. Quindi ho un List<Customer>.

LINQ può essere utilizzato per scoprire se l'elenco ha un cliente con Firstname = 'John'in una singola istruzione .. come?

Risposte:


459

LINQ definisce un metodo di estensione perfetto per risolvere questo problema esatto:

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

assicurati di fare riferimento a System.Core.dll, è qui che vive LINQ.


24
Qualcuno va bene, mi chiedo quanti sviluppatori usano Count quando dovrebbero usare Any?
RichardOD,

12
Puoi anche effettuare una ricerca senza distinzione tra maiuscole e minuscole: cus => cus.FirstName.Equals ("John", StringComparison.CurrentCultureIgnoreCase)
jmservera,

1
So che questa è una vecchia domanda, ma perché non stiamo usando il metodo Exists? Visto che è fatto per vedere se le cose esistono.
Blackunknown il

6
Perché non tutte le raccolte hanno esistenze e non richiede un'espressione lambda, ma piuttosto l'oggetto che stiamo cercando.
Zvolkov,

1
@zvolkov, Qualche idea sul perché il mio resharper mi sta suggerendo di usare bool has = list.All (cus => cus.FirstName! = "John"); È più ottimale?
Gullu,

105

La risposta di zvolkov è quella perfetta per scoprire se esiste un cliente del genere. Se in seguito è necessario utilizzare il cliente, è possibile:

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

So che questo non è quello che mi stavi chiedendo, ma ho pensato di anticipare una domanda successiva :) (Certo, questo trova solo il primo cliente del genere ... per trovarli tutti, basta usare un whereclausola normale .)


7
Vorrei sottolineare che potresti apprezzare di averlo fatto più tardi quando si tratta di debug, se ti trovi improvvisamente curioso di sapere quale cliente corrispondesse ai criteri.
mqp,

1
Basta dare una risposta a questa risposta perché adoro il modo in cui la community SO fa il passo in più per aggiungere ancora di più alla domanda / risposta.
barneymc,

1
grazie mi ha aiutato, ma a volte voglio solo ottenere boolrisultati, quindi in quel caso .Anyo .FindIndexè usato qui che è veloce ?
Shaijut,

1
@stom: Sono entrambi O (N), in sostanza ... sono solo ricerche lineari.
Jon Skeet,

alzando questo. Mi piace il modo in cui usi la sintassi di list.FirstOrDefault invece di fare un elenco.Where (). FirstOrDefault.
GunWanderer,

25

Un'opzione per la seguente domanda (come trovare un cliente che potrebbe avere un numero qualsiasi di nomi):

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

o per recuperare il cliente da CSV di un elenco simile

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

10

Usando Linq hai molte possibilità, qui una senza usare 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")

Ciò non risponde alla domanda "se" esiste una voce del genere; enumera semplicemente i valori se esistono. È necessario un passaggio aggiuntivo per determinare se questa enumerazione non è vuota.
Jason,

Quindi modificare la destinazione. Probabilmente più filosofico per me. Raramente ho bisogno di sapere se senza preoccuparsi di quelli che sono. @jmservera: avevi ragione. Ho rinunciato a LINQ qualche tempo fa e ora uso esclusivamente Lambda.
Chris Brandsma,

Non intendo essere pedante quando dico che l'uso delle chiamate lambda sta ancora tecnicamente usando LINQ. (In particolare, stai usando LINQ-to-Objects.) Stai solo usando le chiamate del metodo piuttosto che le parole chiave del linguaggio.
Judah Gabriel Himango,

In che modo questa risposta differisce da quella di zvolkov?
dotnetN00b,

4

La tecnica che ho usato prima di scoprire .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 sarà nullo se non esiste alcun cliente con un nome di "John".


2
Ciò genererà un'eccezione se più di un cliente si chiama John.
Jon Skeet,

1
Grazie per il commento. Lascerò la risposta come un esempio parzialmente corretto.
M4N,

È ancora valido in uno scenario quando sei sicuro che ci sia 1 e desideri che venga sollevata un'eccezione se più di una, quindi penso che sia positivo che tu non l'abbia eliminata.
RichardOD,

1

Un'altra possibilità

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

4
È preferibile utilizzare Any in questo scenario.
RichardOD,

1

Prova questo, spero che ti aiuti.

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

4
È la stessa risposta accettata di oltre 8 anni fa. Assicurati che la tua risposta sia unica tra tutte le risposte.
Tony_Henrich,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.