myCars.TakeWhile(car => !myCondition(car)).Count();
Ça marche ! Pensez-y. L'indice du premier élément correspondant est égal au nombre d'éléments (non correspondants) qui le précèdent.
L'heure du conte
Moi aussi, je n'aime pas le horrible solution standard que vous avez déjà suggéré dans votre question. Comme la réponse acceptée, j'ai opté pour une bonne vieille boucle, mais avec une légère modification :
public static int FindIndex<T>(this IEnumerable<T> items, Predicate<T> predicate) {
int index = 0;
foreach (var item in items) {
if (predicate(item)) break;
index++;
}
return index;
}
Notez qu'il retournera le nombre d'éléments au lieu de -1
lorsqu'il n'y a pas de correspondance. Mais ignorons cette petite gêne pour l'instant. En fait, le horrible solution standard s'effondre dans ce cas et J'envisage de retourner un index qui est hors limites supérieur .
Ce qui se passe maintenant, c'est que ReSharper me dit La boucle peut être convertie en expression LINQ . Si, la plupart du temps, cette fonctionnalité nuit à la lisibilité, cette fois-ci, le résultat a été époustouflant. Félicitations à JetBrains.
Analyse
Pour
- Concise
- Combinable avec d'autres LINQ
- Évite le site
new
ingérer des objets anonymes
- N'évalue l'énumérable que lorsque le prédicat correspond pour la première fois.
Je considère donc qu'il est optimal dans le temps et l'espace tout en restant lisible.
Cons
- Pas tout à fait évident au début
- Ne revient pas
-1
lorsqu'il n'y a pas de correspondance
Bien sûr, vous pouvez toujours la cacher derrière une méthode d'extension. Et ce qu'il convient de faire lorsqu'il n'y a pas de correspondance dépend fortement du contexte.
0 votes
Similaire : get-list-element-position-in-c-sharp-using-linq
0 votes
Même cette information serait utile - stackoverflow.com/questions/4049773/
7 votes
En fait, il existe un
index
déclaration :var result = items.Select((item, index) => new { index, item });