2010-01-06 23 views
14

tengo el siguiente código¿Cómo puedo limitar la cantidad de elementos iterados en un ciclo foreach?

foreach (var rssItem in rss.Channel.Items) 
{ 
    // ... 
} 

Pero no sólo queremos 6 artículos todos los artículos, ¿cómo puedo hacer que en C#?

+4

¿Qué 6? Cualquier 6? ¿Primero 6? Aleatorio 6? Los 6 que satisfacen un cierto criterio? –

+2

¿Qué versión de .NET? –

+2

Si 'var' está en el código de muestra de la pregunta, es C# 3.0+ –

Respuesta

49

simplemente iterar sobre la parte superior 6 de la colección:

foreach(var rssItem in rss.Channel.Items.Take(6)) 
+6

Cuando dices" demasiado lento ", ¿te refieres al tiempo que lleva iterar sobre la colección o demasiado lento para publicar la respuesta? –

+0

¡Solución impresionante! –

+0

esto no funciona con IList <> –

3
rss.Channel.Items.Take(6) 
5

Uso Enumerable.Take:

foreach(var rssItem in rss.Channel.Items.Take(6)) { 
    // go time! 
} 

Tenga en cuenta que

rss.Channel.Items.Take(6) 

no hace nada más que una instancia de una n implementación de IEnumerable que puede repetirse para producir los primeros seis elementos en la enumeración. Esta es la característica de ejecución diferida de LINQ to Objects.

Tenga en cuenta además que esto supone .NET 3.5. Si está trabajando con una versión anterior de .NET, se puede usar algo en la línea de lo siguiente:

static IEnumerable<T> Take<T>(IEnumerable<T> source, int take) { 
    if (source == null) { 
     throw new ArgumentNullException("source"); 
    } 
    if (take < 0) { 
     throw new ArgumentOutOfRangeException("take"); 
    } 
    if (take == 0) { 
     yield break; 
    } 
    int count = 0; 
    foreach (T item in source) { 
     count++; 
     yield return item; 
     if (count >= take) { 
      yield break; 
     } 
    } 
} 

continuación:

foreach(var rssItem in Take(rss.Channel.Items, 6)) { 
    // go time! 
} 

Esto supone .NET 2.0. Si no está usando .NET 2.0, debería considerar seriamente actualizar.

+0

el rendimiento no está en C# 2, Take tendría que compilar y devolver un nuevo IEnumerable para que funcione si el desarrollador todavía está usando VS2005. –

+3

No, 'yield' es C# 2.0. Los iteradores se introdujeron en C# 2.0/.NET 2.0. cf. http://msdn.microsoft.com/en-us/library/dscyy5s0(VS.80).aspx y http://msdn.microsoft.com/en-us/library/9k7k7cf0(VS.80.aspx – jason

12

de no ser demasiado obvio, pero ...

int max = Math.Min(6, rss.Channel.Items.Count); 
for (int i = 0; i < max; i++) 
{ 
    var rssItem = rss.Channel.Items[i]; 
    //... 
} 

Sé que es de la vieja escuela, y no lleno de todo tipo de método de extensión de la bondad, pero a veces la vieja escuela todavía funciona ... sobre todo si Todavía estoy usando .NET 2.0.

+2

¿Qué sucede si la secuencia no tiene un indexador? Supongamos que es una secuencia infinita de números generados al azar, por ejemplo. –

+0

Aún funcionará para una lista o matriz, que es probablemente rss.Channel.Items. Obviamente, "Tomar" es más simple si Linq es una opción. –

+0

Sugiero una mejora de lenguaje para la versión 5.0 tal vez. para operadores (;;), ++ y similares necesitarían establecer contexto 'oldschool', algo como 'inseguro' actual –

4

Si usted está interesado en una condición (es decir ordenación por fecha de creación)

foreach(var rssItem in rss.Channel.Items.OrderByDescending(x=>x.CreateDate).Take(6)) 
{ 
//do something 
} 

Tal vez si usted quiere conseguir los creados por un determinado usuario, con ese mismo tipo

foreach(var rssItem in rss.Channel.Items 
          .Where(x=>x.UserID == 1) 
          .OrderByDescending(x=>x.CreateDate) 
          .Take(6)) 
{ 
//do something 
} 
4

También podría salir del circuito si no quiere usar linq.

 int count = 0; 
     foreach (var rssItem in rss.Channel.Items) 
     { 
      if (++count == 6) break; 
      ... 
     } 
Cuestiones relacionadas