2009-03-23 13 views
27

Estoy buscando en una lista genérica para encontrar elementos basados ​​en un parámetro determinado.Lista genérica FindAll() vs. foreach

En general, ¿cuál sería la mejor y más rápida implementación?
1. bucle a través de cada elemento de la lista y el ahorro de cada partido a una nueva lista y regresar que

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

return newList; 

O
2. Utilizando el método FindAll y pasándolo a un delegado.

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

¿No funcionan ambos en ~ O (N)? ¿Cuál sería la mejor práctica aquí?

Saludos, Jonathan

Respuesta

41

Definitivamente debe utilizar el método FindAll, o el método LINQ equivalente. Además, considere usar el lambda más conciso en lugar de su delegado si puede (requiere C# 3.0):

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

que usarían el FindAll method en este caso, ya que es más concisa, y la OMI, tiene una mayor legibilidad.

Tienes razón en que están más o menos van a realizar tanto en O (N), aunque el foreach statement debería ser ligeramente más rápido dado que no tiene que realizar una invocación de delegado (delegados incurren en un ligero sobrecarga en oposición a los métodos de llamada directa).

Tengo que insistir en lo insignificante que esta diferencia es que es más que probable que nunca se va a hacer una diferencia a menos que usted está haciendo un gran número de operaciones en una lista masiva.

Como siempre, pruebe para ver dónde están los cuellos de botella y actúe de forma adecuada.

4

List.FindAll es O (n) y buscará en la lista completa.

Si quiere ejecutar su propio iterador con foreach, le recomiendo usar la declaración de rendimiento, y devolver un IEnumerable si es posible. De esta manera, si solo necesita un elemento de su colección, será más rápido (ya que puede detener a su interlocutor sin agotar toda la colección).

De lo contrario, adhiérase a la interfaz BCL.

3

Cualquier diferencia de rendimiento será extremadamente leve. Sugeriría FindAll para mayor claridad o, si es posible, Enumerable. Where. Prefiero usar los métodos Enumerable porque permite una mayor flexibilidad para refactorizar el código (no toma una dependencia en List<T>).

5

Jonathan,

Una buena respuesta se puede encontrar a esto es en el capítulo 5 (consideraciones de rendimiento) de Linq To Action.

Miden una para cada búsqueda que se ejecuta unas 50 veces y que viene con foreach = 68ms por ciclo/List.FindAll = 62ms por ciclo. En realidad, probablemente te interese solo crear una prueba y ver por ti mismo.

2

Sí, ambas implementaciones son O (n). Necesitan mirar cada elemento en la lista para encontrar todas las coincidencias. En términos de legibilidad también preferiría FindAll. Para consideraciones de rendimiento, consulte LINQ in Action (capítulo 5.3). Si está usando C# 3.0 también puede aplicar una expresión lambda. Pero eso es sólo la guinda del pastel:

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

Im con los Lambdas

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

A menos que el C# equipo ha mejorado el rendimiento de LINQ y FindAll, el siguiente artículo parece sugerir que for y foreach superaría a LINQ y FindAll en la enumeración de objetos: LINQ on Objects Performance.

Esta artilce se remonta a marzo de 2009, justo antes de esta publicación originalmente solicitada.