Pesquisando se existe valor em uma lista de objetos usando o Linq

228

Digamos que eu tenha uma classe Customerque tenha uma propriedade FirstName. Então eu tenho umList<Customer> .

O LINQ pode ser usado para descobrir se a lista possui um cliente Firstname = 'John'em uma única instrução. Como?

Tony_Henrich
fonte

Respostas:

459

O LINQ define um método de extensão perfeito para resolver esse problema exato:

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

certifique-se de referenciar System.Core.dll, é onde mora o LINQ.

zvolkov
fonte
24
Qualquer um é bom, gostaria de saber quantos desenvolvedores usam o Count quando devem usar o Qualquer?
21410 RichardOD
12
Você também pode fazer um caso de busca insensível: cus => cus.FirstName.Equals ( "John", StringComparison.CurrentCultureIgnoreCase)
jmservera
1
Sei que essa é uma pergunta antiga, mas por que não estamos usando o método Exists? Vendo como é feito para ver se as coisas existem.
Blackunknown
6
Como nem todas as coleções existem, ela não recebe uma expressão lambda, mas o objeto que estamos procurando.
Zvolkov 9/07
1
@zvolkov, Alguma idéia de por que meu resharper está sugerindo que eu use o bool has = list.All (cus => cus.FirstName! = "John"); Isso é mais ideal?
Gullu
105

A resposta de zvolkov é perfeita para descobrir se existe um cliente assim. Se você precisar usar o cliente posteriormente, poderá:

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

Sei que não era isso que você estava perguntando, mas pensei em antecipar uma pergunta subsequente :) (é claro, isso só encontra o primeiro cliente desse tipo ... para encontrar todos eles, basta usar um wherecláusula normal .)

Jon Skeet
fonte
7
Eu gostaria de salientar que você pode gostar de ter feito isso mais tarde quando se trata de depuração, se você ficar subitamente curioso sobre qual cliente foi o que se encaixa nos critérios.
Mqp 01/07/2009
1
Apenas aumentando essa resposta em um ponto, porque eu amo a maneira como a comunidade dá o passo extra para adicionar ainda mais à pergunta / resposta.
Barneymc
1
obrigado me ajudou, mas às vezes eu só quero obter boolresultado, então nesse caso .Anyou .FindIndexé usado aqui o que é rápido ?
shaijut 6/03/19
1
@ stom: Ambos são O (N), basicamente ... são apenas pesquisas lineares.
Jon Skeet
aumentando isso. Eu gosto da maneira como você usa a sintaxe de list.FirstOrDefault em vez de fazer uma list.Where (). FirstOrDefault.
GunWanderer
25

Uma opção para a pergunta a seguir (como encontrar um cliente que possa ter qualquer número de nomes):

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

ou recuperar o cliente do csv da lista semelhante

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

Usando o Linq você tem muitas possibilidades, aqui uma sem o uso de lambdas:

//assuming list is a List<Customer> or something queryable...
var hasJohn = (from customer in list
         where customer.FirstName == "John"
         select customer).Any();
jmservera
fonte
5
customerList.Any(x=>x.Firstname == "John")
Chris Brandsma
fonte
Isso não responde à pergunta "se" existe uma entrada; apenas enumera os valores, se existirem. Uma etapa extra é necessária para determinar se essa enumeração é vazia.
jason
Em seguida, altere Onde para Qualquer. Provavelmente mais filosófico para mim. Eu raramente preciso saber se, sem me importar com quem eles são. @ jmservera: você estava certo. Desisti do LINQ há um tempo e agora uso o Lambda exclusivamente.
Chris Chrisma
Não quero ser pedante quando digo que o uso das chamadas lambda ainda está tecnicamente usando o LINQ. (Em particular, você está usando LINQ-to-Objects.) Você está apenas usando as chamadas de método, e não as palavras-chave do idioma.
Judah Gabriel Himango
Como essa resposta difere da de zvolkov?
DotnetN00b
4

A técnica que usei antes de descobrir .Any():

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

john será nulo se não existir um cliente com o primeiro nome de "John".

M4N
fonte
2
Isso gerará uma exceção se mais de um cliente for chamado John.
911 Jon Skeet
1
Obrigado pelo comentário. Deixarei a resposta como um exemplo parcialmente correto.
M4N
Ainda é válido em um cenário quando você tem certeza de que existe 1 e deseja que uma exceção seja levantada se houver mais de um, por isso acho bom que você não a excluiu.
21410 RichardOD
1

Outra possibilidade

if (list.Count(customer => customer.Firstname == "John") > 0) {
 //bla
}
Krassi
fonte
4
É preferível usar Qualquer um nesse cenário.
RichardOD
1

Tente isso, espero que ajude você.

 if (lstCustumers.Any(cus => cus.Firstname == "John"))
 {
     //TODO CODE
 }
Fabio Stratotti
fonte
4
É o mesmo que a resposta aceita há mais de 8 anos. Verifique se a sua resposta é única entre todas as respostas.
Tony_Henrich