2009-07-24 7 views
169

Ici, j'ai un exemple simple pour trouver un élément dans une liste de chaînes. Normalement j'utilise pour la boucle ou délégué anonyme pour le faire comme ceci:Trouvez un article dans la liste par LINQ?

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 savoir si je peux utiliser LINQ pour trouver un élément dans la liste? Comment si possible?

+0

C'est génial. Cependant, ce sont tous des styles d'expression lamda. J'utilise une liste simple ici. La liste peut être une classe avec plusieurs propriétés et certaines sont utilisées pour la recherche. Donc, n'importe quel moyen LINQ de rechercher comme "de .. dans ... où ... sélectionnez ..." –

+0

Nah, désolé. La plupart de ces méthodes (First, Single, Any, ...) ne peuvent pas être * directement * traduites dans cette forme. –

+0

Peu importe, en fait, vous pouvez vous débarrasser des lambdas pour quelques cas ... –

Répondre

364

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

1) Single retournera un résultat unique, mais jetteront une exception si elle en trouve pas ou plus d'un (qui peut ou peut 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 pareil, sauf qu'il retournera null pour les types de référence, ou la valeur par défaut pour les types de valeur, au lieu de lancer une exception.

2) Where renverra tous les articles qui correspondent à vos critères, vous pouvez 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); 

La note FirstOrDefault() se comportera de la même manière, sauf qu'elle renverra null pour les types de référence, ou la valeur par défaut pour les types de valeur, au lieu de générer une exception.

+30

Bonne réponse.J'ai trouvé que SingleOrDefault est ma réponse de choix - identique à Single mais renvoie 'null' s'il ne peut pas le trouver. –

+2

Je ne connaissais ni Single() ni SingleOrDefault(). Très utile. – draconis

+0

Ces méthodes peuvent-elles être utilisées avec d'autres collections comme 'ReadOnlyCollection' ou' ObservableCollection'? – yellavon

65

Si vous voulez que l'index de l'élément, ce 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 dans la première passe.

Notez que cela se déclenchera si l'élément n'existe pas. Cela résout le problème en ayant recours à nullables ints:

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 voulez compter le nombre d'éléments qui correspondent à:

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 éléments 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 l'un de ces cas.

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

Merci à Pavel pour son aide dans les commentaires.

+2

Deux points. Tout d'abord, il n'y a pas vraiment besoin d'utiliser 'string.Equals' ici - rien de mal avec' == '. Deuxièmement, je mentionnerais également 'FirstOrDefault' (pour les cas où l'élément pourrait ne pas être présent), et' Select' avec l'index pour couvrir le cas où l'index de l'élément est nécessaire (comme dans l'exemple de la question). –

+0

Merci de les signaler. –

+0

Je ne suis pas encore content. Il n'y a pas d'index -1 (non trouvé) dans mon exemple. Toute suggestion? –

12

Si c'est vraiment un List<string> vous n'avez pas besoin LINQ, il suffit d'utiliser:

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

Si vous êtes à la recherche de l'élément lui-même, essayez:

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

En suivant la logique du premier exemple, nous pourrions utiliser '_list.Find (search)' pour la seconde. – jwg

9

Voulez-vous que l'élément dans la liste ou l'article lui-même (supposerait l'article 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); 
+0

Whoa ... certaines personnes sont super rapides le déclencheur;) – Kelsey

+0

que diriez-vous de l'index comme valeur de retour? –

+0

et dois-je vérifier si _list est null sous la forme de from .. in _list ...? –

2

Je l'habitude d'utiliser un dictionnaire qui est une sorte d'une 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); 

Chaque fois que je souhaite accéder à mes valeurs des marges, par exemple, j'adresse mon dictionnaire:

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

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

+0

Grande réponse à une question différente. – jwg

6

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

var lOrders = new List<string>(); 

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

+1

Je pense que nous n'avons même pas besoin de 'true: false' ci-dessous devrait fonctionner même ' bool insertOrderNew = lOrders.Find (r => r == "1234") == null; ' – Vbp

5

Que diriez-vous IndexOf?

Recherche l'objet spécifié et retourne 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 se produit pas dans la liste

> boys.IndexOf("Hermione") 
-1 
2

Voici une façon de réécrire votre méthode pour utiliser L INQ:

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

1

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

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

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

Cette recherche trouvera la première ou valeur par défaut, il reviendra.

1

Si nous avons besoin de trouver un élément de la liste, alors nous pouvons utiliser la méthode des extensions Find et FindAll, mais il y a une légère différence entre elles. 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); 
0

Vous souhaitez 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 Linq List.

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

ou

var item = (from items in list 
    where items.Reference == ent.BackToBackExternalReferenceId 
    select items).FirstOrDefault(); 
Questions connexes