267 votes

Comment puis-je obtenir l'indice d'un élément d'une liste en une seule étape ?

Comment puis-je trouver l'index d'un élément dans une liste sans la parcourir en boucle ?

Actuellement, cela n'a pas l'air très agréable - chercher deux fois le même élément dans la liste, juste pour obtenir l'index :

var oProp = something;

int theThingIActuallyAmInterestedIn = myList.IndexOf(myList.Single(i => i.Prop == oProp));

0 votes

535voto

Alex Filipovici Points 14194

Que pensez-vous de la Méthode List.FindIndex :

int index = myList.FindIndex(a => a.Prop == oProp);

Cette méthode effectue une recherche linéaire ; par conséquent, cette méthode est une opération O(n), où n est le nombre.

Si l'élément n'est pas trouvé, il retournera -1

2 votes

Et si int index ?

2 votes

DylanChensky, il a trop codé JS.

12 votes

Pour référence, si l'élément n'est pas trouvé, il renvoie -1.

131voto

Pour les types simples, vous pouvez utiliser "IndexOf" :

List<string> arr = new List<string>();
arr.Add("aaa");
arr.Add("bbb");
arr.Add("ccc");
int i = arr.IndexOf("bbb"); // Returns 1.

0 votes

Comment définissez-vous les "types simples" ? Les types scalaires ?

0 votes

@PeterMortensen, oui !

1 votes

Ceci renvoie également -1 si l'élément n'est pas trouvé. Comme Jose l'a déjà mentionné, si vous utilisez disons List<string> C'est la voie à suivre, mais elle n'est pas réalisable pour les listes d'objets complexes.

87voto

Jon Skeet Points 692016

EDIT : Si vous êtes uniquement en utilisant un List<> et vous uniquement ont besoin de l'index, alors List.FindIndex est en effet la meilleure approche. Je vais laisser cette réponse ici pour ceux qui ont besoin de quelque chose de différent (par exemple, au-dessus de n'importe quel IEnumerable<> ).

Utilisez la surcharge de Select qui prend un index dans le prédicat, donc vous transformez votre liste en une paire (index, valeur) :

var pair = myList.Select((Value, Index) => new { Value, Index })
                 .Single(p => p.Value.Prop == oProp);

Ensuite :

Console.WriteLine("Index:{0}; Value: {1}", pair.Index, pair.Value);

Ou si vous uniquement vous voulez l'index et que vous l'utilisez à plusieurs endroits, vous pourriez facilement écrire votre propre méthode d'extension comme suit Where mais au lieu de renvoyer les éléments originaux, elle renvoie les index des éléments qui correspondent au prédicat.

1 votes

On dirait que tout ce qu'il veut, c'est l'indice. List<>.FindIndex(Predicate<>) est la meilleure approche. Bien que le titre de la question laisse entendre le contraire, la description de l'OP est assez claire : il n'a besoin que de l'index "int theThingIActuallyAmInterestedIn".

1 votes

@LastCoder : Aha - j'avais manqué FindIndex. Oui, je suis tout à fait d'accord.

1 votes

Pour être clair, l'approche "index/valeur -> simple" est-elle "meilleure" (c'est-à-dire plus rapide en termes de Big-O) qu'une double itération manuelle ? Ou le fournisseur LINQ2Objects est-il suffisamment intelligent pour optimiser l'une des itérations ? (Je pars du principe que les opérations Select et Single sont généralement des opérations O(n)).

16voto

gzaxx Points 11117

Si vous ne voulez pas utiliser LINQ, alors :

int index;
for (int i = 0; i < myList.Count; i++)
{
    if (myList[i].Prop == oProp)
    {
       index = i;
       break;
    }
}

De cette façon, vous ne faites qu'une seule itération de la liste.

22 votes

@KingKing personne n'a dit que c'était le cas.

1 votes

S'agit-il de la même mise en œuvre que Linq FindIndex par intérêt ?

2 votes

Ce n'est probablement pas le même code, List a quelques optimisations intéressantes ici et là. Mais j'ai du mal à croire qu'ils puissent rechercher une liste non ordonnée en moins de O(n), donc je dirais qu'ils sont probablement très similaires en pratique.

10voto

  1. Une solution simple pour trouver l'index de n'importe quelle valeur de chaîne dans la liste.

    Voici le code pour une liste de chaînes de caractères :

     int indexOfValue = myList.FindIndex(a => a.Contains("insert value from list"));
  2. Une solution simple pour trouver l'index de n'importe quel entier dans la liste.

    Voici le code pour une liste d'entiers :

     int indexOfNumber = myList.IndexOf(/* insert number from list */);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X