Si entiendo su pregunta correctamente, está tratando de crear una implementación diferida de un enumerador que divide una colección más grande de elementos en colecciones enumerables más pequeñas de elementos.
Por ejemplo, una secuencia de un millón de números podría dividirse en "secciones", cada uno produciendo solo 100 de ellos, y usted lo quiere todo de forma perezosa, es decir. no recolectar 100 elementos en una lista antes de producirlos.
Primero, sus intentos se repetirán varias veces sobre la colección, lo cual es malo, de ahí el problema de rendimiento.
Si usted está tratando de construir una aplicación pura pereza, debe tener en cuenta las siguientes cuestiones:
- Usted quiere iterar sobre la colección subyacente sola vez
- Debe volver enumerables que re-uso el enumerador subyacente
- Debe controlar que una sección que devuelve no esté completamente enumerada (por ejemplo, el código de llamada solo necesitó los primeros 50 de esos 100 elementos).
Editar: Antes de entrar en mi solución simplista, aquí hay algunas advertencias al respecto:
- no se puede guardar cada sección para más tarde, es decir. no puede hacer:
collection.Sequence(10).ToArray()
para obtener una matriz de secciones.
- No puede enumerar cada sección más de una vez, porque cuando lo hace, cambia una estructura oculta de datos subyacente.
Básicamente: Mi solución no es de uso general.Debería ir con el comentario @LBushkin sobre MoreLinq Lote si necesita esto, y dudaría en poner mi código en una biblioteca de clase, tendría que ser local donde se necesita, o renombrarse a algo que claramente lo advierta sobre la problemas con eso.
Aquí hay una aplicación simplista, estoy bastante seguro de que hay errores aquí, así que puede que desee ver en la implementación de una tonelada de pruebas unitarias para edgecases:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication20
{
class SectionEnumerable<T> : IEnumerable<T>
{
private readonly IEnumerator<T> _Enumerator;
public SectionEnumerable(IEnumerator<T> enumerator, int sectionSize)
{
_Enumerator = enumerator;
Left = sectionSize;
}
public IEnumerator<T> GetEnumerator()
{
while (Left > 0)
{
Left--;
yield return _Enumerator.Current;
if (Left > 0)
if (!_Enumerator.MoveNext())
break;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int Left { get; private set; }
}
static class SequenceExtensions
{
public static IEnumerable<IEnumerable<T>> Section<T>(this IEnumerable<T> collection, int sectionSize)
{
if (collection == null)
throw new ArgumentNullException("collection");
if (sectionSize < 1)
throw new ArgumentOutOfRangeException("sectionSize");
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
SectionEnumerable<T> enumerable = new SectionEnumerable<T>(enumerator, sectionSize);
yield return enumerable;
for (int index = 0; index < enumerable.Left; index++)
if (!enumerator.MoveNext())
yield break;
}
}
}
}
class Program
{
static void Main(string[] args)
{
var sequence = Enumerable.Range(0, 100);
var sections = sequence.Section(10);
foreach (var section in sections)
{
Console.WriteLine(
String.Join(", ",
section.Take(5).ToArray().Select(i => i.ToString()).ToArray()));
}
Console.ReadLine();
}
}
}
Salida:
0, 1, 2, 3, 4
10, 11, 12, 13, 14
20, 21, 22, 23, 24
30, 31, 32, 33, 34
40, 41, 42, 43, 44
50, 51, 52, 53, 54
60, 61, 62, 63, 64
70, 71, 72, 73, 74
80, 81, 82, 83, 84
90, 91, 92, 93, 94
cosas que debe unidad de prueba:
- colección de entrada vacío no produce secciones
- Una colección que tiene el número correcto de elementos, produce sólo una sección
- Una colección que contiene una multiplum de los elementos de sección de tamaño, (es decir. 10, 20, 30, etc. número de elementos con un tamaño de sección de 5 o 10), no produce una sección vacía después de todas las esperadas
- Que es realmente vago, si enumera sobre los primeros 10- sección del elemento, pero solo los primeros 5 de la segunda sección, solo los primeros 15 elementos de la colección subyacente se enumeran en
Creo que el segundo es más fácil de leer en mi humilde opinión – JoshBerke
¿Qué es Enumerar()? – BFree
¿Puede darnos un resumen rápido de cuál es su objetivo con la función de sección? Parece que estás tratando de tomar un IEnumerable y enumerarlo obteniendo un nuevo IEnumerable con elementos de longitud cada vez ¿no? – JoshBerke