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?

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.


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


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

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

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

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;

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


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
}

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
 }

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.