Buscando si el valor existe en una lista de objetos usando Linq

228

Digamos que tengo una clase Customer que tiene una propiedad FirstName. Entonces tengo un List<Customer>.

¿Se puede usar LINQ para encontrar si la lista tiene un cliente Firstname = 'John'en una sola declaración ... cómo?

Tony_Henrich
fuente

Respuestas:

459

LINQ define un método de extensión que es perfecto para resolver este problema exacto:

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

asegúrese de hacer referencia a System.Core.dll, ahí es donde vive LINQ.

zvolkov
fuente
24
Cualquiera es bueno, me pregunto cuántos desarrolladores usan Count cuando deberían usar Any.
RichardOD 01 de
12
También puede hacer una búsqueda sin distinción entre mayúsculas y minúsculas: cus => cus.FirstName.Equals ("John", StringComparison.CurrentCultureIgnoreCase)
jmservera
1
Sé que esta es una vieja pregunta, pero ¿por qué no estamos utilizando el método Exists? Viendo como está hecho para ver si las cosas existen.
Blackunknown
66
Porque no todas las colecciones tienen Exists, y no toma una expresión lambda, sino el objeto que estamos buscando.
zvolkov
1
@zvolkov, ¿Alguna idea de por qué mi investigador sugiere que use bool has = list.All (cus => cus.FirstName! = "John"); ¿Es esto más óptimo?
Gullu
105

La respuesta de zvolkov es la perfecta para saber si existe tal cliente. Si necesita utilizar al cliente después, puede hacer lo siguiente:

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

Sé que esto no es lo que estabas preguntando, pero pensé que preferiría una pregunta de seguimiento :) (Por supuesto, esto solo encuentra el primer cliente de este tipo ... para encontrarlos a todos, solo usa un wherecláusula normal .)

Jon Skeet
fuente
77
Debo señalar que puede agradecerle haber hecho esto más adelante cuando se trata de depuración, si de repente siente curiosidad sobre qué cliente fue el que cumplió con los criterios.
mqp
1
Simplemente aumente esta respuesta porque me encanta la forma en que la comunidad SO da el paso adicional para agregar aún más a la pregunta / respuesta.
barneymc
1
gracias me ayudó, pero a veces solo quiero obtener boolresultados, así que en ese caso .Anyo .FindIndexse usa aquí, ¿ qué es rápido ?
shaijut
1
@stom: Ambos son O (N), básicamente ... son solo búsquedas lineales.
Jon Skeet
subiendo esto. Me gusta cómo usas la sintaxis de list.FirstOrDefault en lugar de hacer una lista.Where (). FirstOrDefault.
GunWanderer
25

Una opción para la siguiente pregunta (cómo encontrar un cliente que pueda tener cualquier número de nombres):

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

o para recuperar al cliente del csv de una lista similar

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

Usando Linq tienes muchas posibilidades, aquí una sin usar lambdas:

//assuming list is a List<Customer> or something queryable...
var hasJohn = (from customer in list
         where customer.FirstName == "John"
         select customer).Any();
jmservera
fuente
5
customerList.Any(x=>x.Firstname == "John")
Chris Brandsma
fuente
Esto no responde a la pregunta "si" existe tal entrada; simplemente enumera los valores si existen. Se necesita un paso adicional para determinar si esta enumeración no es vacía.
jason
Luego cambie el Dónde a Cualquiera. Probablemente más filosófico para mí. Raramente necesito saber si sin importar cuáles son. @jmservera: tenías razón. Renuncié a LINQ hace un tiempo y ahora uso Lambda exclusivamente.
Chris Brandsma
No pretendo ser pedante cuando digo que usar las llamadas lambda sigue siendo técnicamente usar LINQ. (En particular, está utilizando LINQ-to-Objects). Solo está utilizando las llamadas al método en lugar de las palabras clave del idioma.
Judá Gabriel Himango
¿Cómo difiere esta respuesta de la de zvolkov?
dotnetN00b
4

La técnica que utilicé antes de descubrir .Any():

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

John será nulo si no existe un cliente con un nombre de pila "John".

M4N
fuente
2
Eso arrojará una excepción si más de un cliente se llama John.
Jon Skeet el
1
Gracias por el comentario. Dejaré la respuesta como un ejemplo parcialmente correcto.
M4N 01 de
Todavía es válido en un escenario cuando está seguro de que hay 1 y desea que se genere una excepción si hay más de uno, por lo que creo que es bueno que no lo haya eliminado.
RichardOD 01 de
1

Otra posibilidad

if (list.Count(customer => customer.Firstname == "John") > 0) {
 //bla
}
Krassi
fuente
44
Es preferible usar Any en este escenario.
RichardOD 01 de
1

Prueba esto, espero que te ayude.

 if (lstCustumers.Any(cus => cus.Firstname == "John"))
 {
     //TODO CODE
 }
Fabio Stratotti
fuente
44
Es lo mismo que la respuesta aceptada de hace más de 8 años. Asegúrese de que su respuesta sea única entre todas las respuestas.
Tony_Henrich