2009-03-23 9 views
27

Je suis à la recherche d'une liste générique pour trouver des éléments basés sur un certain paramètre.Liste générique FindAll() vs. foreach

En général, quelle serait la meilleure et la plus rapide mise en œuvre?
1. Looping à travers chaque élément de la liste et de sauver chaque match à une nouvelle liste et retour qui

foreach(string s in list) 
{ 
    if(s == "match") 
    { 
     newList.Add(s); 
    } 
} 

return newList; 

ou
2. En utilisant la méthode FindAll et le passage d'un délégué.

newList = list.FindAll(delegate(string s){return s == "match";}); 

Ne fonctionnent-ils pas tous les deux dans ~ O (N)? Quelle serait la meilleure pratique ici?

Cordialement, Jonathan

Répondre

41

Vous devez absolument utiliser la méthode FindAll ou la méthode LINQ équivalente. En outre, pensez à utiliser le lambda plus concis au lieu de votre délégué si vous le pouvez (nécessite C# 3.0):

var list = new List<string>(); 
var newList = list.FindAll(s => s.Equals("match")); 
9

J'utiliseraient le FindAll method dans ce cas, car il est plus concis, et l'OMI, a facilité la lisibilité.

Vous avez raison qu'ils sont à peu près vont à la fois effectuer en O (n), bien que le foreach statementdevrait être légèrement plus rapide étant donné qu'il n'a pas à effectuer un appel de délégué (délégués encourent une légère frais généraux par opposition aux méthodes d'appel direct).

je dois souligner à quel point cette différence insignifiante est, il est plus que probable de ne jamais faire une différence à moins que vous faites un nombre massif des opérations sur une liste massif.

Comme toujours, testez pour voir où se trouvent les goulets d'étranglement et agissez de manière appropriée.

4

List.FindAll est O (n) et recherchera toute la liste.

Si vous voulez exécuter votre propre itérateur avec foreach, je vous recommande d'utiliser l'instruction yield et de renvoyer un IEnumerable si possible. De cette façon, si vous n'avez besoin que d'un élément de votre collection, ce sera plus rapide (puisque vous pouvez arrêter votre appelant sans épuiser toute la collection).

Sinon, respectez l'interface BCL.

3

Toute différence de performance sera extrêmement mineure. Je suggère FindAll pour plus de clarté, ou, si possible, Enumerable.Where. Je préfère utiliser les méthodes Enumerable car cela permet une plus grande flexibilité dans la refactorisation du code (vous ne dépendez pas de List<T>).

5

Jonathan,

Une bonne réponse vous pouvez trouver à cette question est dans le chapitre 5 (considérations de performance) de Linq To Action.

Ils mesurent un pour chaque recherche qui s'exécute environ 50 fois et qui revient à foreach = 68ms par cycle/List.FindAll = 62ms par cycle. Vraiment, il serait probablement dans votre intérêt de simplement créer un test et de voir par vous-même.

2

Oui, les deux implémentations sont O (n). Ils doivent regarder chaque élément de la liste pour trouver tous les résultats. En termes de lisibilité, je préférerais aussi FindAll. Pour des considérations de performance, jetez un oeil à LINQ in Action (Ch 5.3). Si vous utilisez C# 3.0, vous pouvez également appliquer une expression lambda. Mais c'est la cerise sur le gâteau:

var newList = aList.FindAll(s => s == "match"); 
1

Im avec les lambdas

List<String> newList = list.FindAll(s => s.Equals("match")); 
0

À moins que l'équipe C# a amélioré la performance pour LINQ et FindAll, l'article suivant semble suggérer que for et foreach surpasserait LINQ et FindAll sur l'énumération d'objets: LINQ on Objects Performance.

Cet artilce était daté de mars 2009, juste avant que ce poste ne le demande à l'origine.

Questions connexes