web-dev-qa-db-fra.com

Rechercher un élément dans la liste par LINQ?

Ici, j'ai un exemple simple pour trouver un élément dans une liste de chaînes. J'utilise normalement for for ou un délégué anonyme pour le faire comme ceci:

int GetItemIndex(string search)
{
   int found = -1;
   if ( _list != null )
   {
     foreach (string item in _list) // _list is an instance of List<string>
     { 
        found++;
        if ( string.Equals(search, item) )
        {
           break;
        }
      }
      /* use anonymous delegate
      string foundItem = _list.Find( delegate(string item) {
         found++;
         return string.Equals(search, item);
      });
      */
   }
   return found;
}

LINQ est nouveau pour moi. Je suis curieux de pouvoir utiliser LINQ pour trouver un élément dans la liste? Comment si possible?

199
David.Chu.ca

Il y a plusieurs façons (notez que ceci est non une liste complète).

1) Single renverra un seul résultat, mais lèvera une exception s'il n'en trouve aucun ou plus d'un (ce qui peut être ou ne pas être ce que vous voulez):

string search = "lookforme";
List<string> myList = new List<string>();
string result = myList.Single(s => s == search);

Remarque: SingleOrDefault() se comportera de la même façon, sauf qu'il renverra null pour les types de référence ou la valeur par défaut pour les types de valeur, au lieu de déclencher une exception.

2) renverra tous les éléments correspondant à vos critères afin que vous puissiez obtenir un IEnumerable avec un élément:

IEnumerable<string> results = myList.Where(s => s == search);

3) First renverra le premier élément qui correspond à vos critères:

string result = myList.First(s => s == search);

Remarque: FirstOrDefault() se comportera de la même façon, sauf qu'il renverra null pour les types de référence ou la valeur par défaut pour les types de valeur, au lieu de déclencher une exception.

424
Rex M

Si vous voulez l'index de l'élément, ceci le fera:

int index = list.Select((item, i) => new { Item = item, Index = i })
                .First(x => x.Item == search).Index;

// or
var tagged = list.Select((item, i) => new { Item = item, Index = i });
int index = (from pair in tagged
            where pair.Item == search
            select pair.Index).First();

Vous ne pouvez pas vous débarrasser du lambda lors du premier passage.

Notez que cela jettera si l'élément n'existe pas. Cela résout le problème en recourant à des in nullables:

var tagged = list.Select((item, i) => new { Item = item, Index = (int?)i });
int? index = (from pair in tagged
            where pair.Item == search
            select pair.Index).FirstOrDefault();

Si vous voulez l'article:

// Throws if not found
var item = list.First(item => item == search);
// or
var item = (from item in list
            where item == search
            select item).First();

// Null if not found
var item = list.FirstOrDefault(item => item == search);
// or
var item = (from item in list
            where item == search
            select item).FirstOrDefault();

Si vous souhaitez compter le nombre d’éléments correspondants:

int count = list.Count(item => item == search);
// or
int count = (from item in list
            where item == search
            select item).Count();

Si vous voulez tous les articles qui correspondent:

var items = list.Where(item => item == search);
// or
var items = from item in list
            where item == search
            select item;

Et n'oubliez pas de vérifier la liste pour null dans aucun de ces cas.

Ou utilisez (list ?? Enumerable.Empty<string>()) au lieu de list.

Merci à Pavel pour son aide dans les commentaires.

70

Si c'est vraiment un List<string> vous n'avez pas besoin de LINQ, utilisez simplement:

int GetItemIndex(string search)
{
    return _list == null ? -1 : _list.IndexOf(search);
}

Si vous recherchez l'élément lui-même, essayez:

string GetItem(string search)
{
    return _list == null ? null : _list.FirstOrDefault(s => s.Equals(search));
}
13
AgileJon

Voulez-vous l'élément dans la liste ou l'élément lui-même (supposerait l'élément lui-même).

Voici un tas d'options pour vous:

string result = _list.First(s => s == search);

string result = (from s in _list
                 where s == search
                 select s).Single();

string result = _list.Find(search);

int result = _list.IndexOf(search);
10
Kelsey

Cette méthode est plus facile et plus sûre

var lOrders = new List<string>();

bool insertOrderNew = lOrders.Find(r => r == "1234") == null ? true : false

6
RckLN

Que diriez-vous de IndexOf

Recherche l'objet spécifié et renvoie l'index de la première occurrence dans la liste.

Par exemple

> var boys = new List<string>{"Harry", "Ron", "Neville"};  
> boys.IndexOf("Neville")  
2
> boys[2] == "Neville"
True

Notez qu'il renvoie -1 si la valeur ne figure pas dans la liste 

> boys.IndexOf("Hermione")  
-1
5
Colonel Panic

Voici un moyen de réécrire votre méthode pour utiliser LINQ:

public static int GetItemIndex(string search)
{
    List<string> _list = new List<string>() { "one", "two", "three" };

    var result = _list.Select((Value, Index) => new { Value, Index })
            .SingleOrDefault(l => l.Value == search);

    return result == null ? -1 : result.Index;
}

Ainsi, l'appelant avec

GetItemIndex("two") retournera 1,

et

GetItemIndex("notthere") retournera -1.

Référence: linqsamples.com

2
brinch

J'avais l'habitude d'utiliser un dictionnaire qui est une sorte de liste indexée qui me donnera exactement ce que je veux quand je le veux.

Dictionary<string, int> margins = new Dictionary<string, int>();
margins.Add("left", 10);
margins.Add("right", 10);
margins.Add("top", 20);
margins.Add("bottom", 30);

Par exemple, chaque fois que je souhaite accéder à mes valeurs de marges, je m'adresse à mon dictionnaire:

int xStartPos = margins["left"];
int xLimitPos = margins["right"];
int yStartPos = margins["top"];
int yLimitPos = margins["bottom"];

Donc, selon ce que vous faites, un dictionnaire peut être utile.

2
Will Marcouiller

Si nous devons rechercher un élément dans la liste, nous pouvons utiliser la méthode des extensions Find et FindAll, mais il existe une légère différence entre eux. Voici un exemple.

 List<int> items = new List<int>() { 10, 9, 8, 4, 8, 7, 8 };

  // It will return only one 8 as Find returns only the first occurrence of matched elements.
     var result = items.Find(ls => ls == 8);      
 // this will returns three {8,8,8} as FindAll returns all the matched elements.
      var result1 = items.FindAll(ls => ls == 8); 
1
Sheo Dayal Singh

Cela vous aidera à obtenir la première valeur ou la valeur par défaut dans votre recherche dans la liste Linq.

var results = _List.Where(item => item == search).FirstOrDefault();

Cette recherche trouvera la première valeur ou la valeur par défaut à renvoyer.

1
user1407955

Essayez ce code: 

return context.EntitytableName.AsEnumerable().Find(p => p.LoginID.Equals(loginID) && p.Password.Equals(password)).Select(p => new ModelTableName{ FirstName = p.FirstName, UserID = p.UserID });
1
Nayeem Mansoori

Vous voulez rechercher un objet dans la liste d'objets.

Cela vous aidera à obtenir la première valeur ou la valeur par défaut dans votre recherche dans la liste Linq.

var item = list.FirstOrDefault(items =>  items.Reference == ent.BackToBackExternalReferenceId);

ou

var item = (from items in list
    where items.Reference == ent.BackToBackExternalReferenceId
    select items).FirstOrDefault();
0
Huseyin Durmus