Se ho compreso correttamente la tua domanda, stai cercando di creare un'implementazione lenta di un enumeratore che divide una più ampia raccolta di elementi in raccolte di oggetti enumerabili più piccole.
Ad esempio, una sequenza di un milione di numeri può essere suddivisa in "sezioni", ognuna delle quali ne produce solo 100, e si desidera che tutto funzioni pigramente, cioè. non raccogliere 100 elementi in una lista prima di produrli.
In primo luogo, i tentativi tenteranno di ripetere la raccolta più volte, il che è negativo, quindi il problema delle prestazioni.
Se si sta cercando di costruire un'implementazione pigro pura, si dovrebbe prendere in considerazione i seguenti aspetti:
- Si vuole iterare l'insieme sottostante solo una volta
- Si dovrebbe tornare enumerables che ri-uso l'enumeratore sottostante
- È necessario gestire che una sezione che si restituisce non sia completamente enumerata (ad esempio, il codice chiamante aveva solo bisogno dei primi 50 di quei 100 elementi).
Edit: Prima di andare nella mia soluzione semplicistica, ecco alcune precisazioni al riguardo:
- Non è possibile salvare ogni sezione per dopo, vale a dire. non puoi fare:
collection.Sequence(10).ToArray()
per ottenere una serie di sezioni.
- Non è possibile enumerare su ciascuna sezione più di una volta, perché quando lo si fa, cambia una struttura di dati sottostante nascosta.
In sostanza: mia soluzione non è di uso generale.Dovresti andare con il commento di @LBushkin su MoreLinq Batch se ne hai bisogno, e esiterei a mettere il mio codice in una libreria di classi, dovrebbe essere locale dove è necessario, o rinominato in qualcosa che ti avvisa chiaramente del problemi con esso.
Ecco un'implementazione semplicistico, sono abbastanza sicuro che ci sono bug qui, così si potrebbe desiderare di guardare ad attuare una tonnellata di unit test per 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();
}
}
}
uscita:
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
cose che si dovrebbero unità-test:
- raccolta ingresso vuoto non produce sezioni
- Una collezione che ha appena il giusto numero di elementi, produce solo una sezione
- Una collezione che contiene una multiplum degli elementi sezione dimensioni, (cioè. 10, 20, 30, ecc. Numero di elementi con una sezione di 5 o 10), non produce una sezione vuota dopo tutti quelli attesi
- Che in realtà è pigro, se si enumera il primo 10- sezione elemento, ma solo i primi 5 della seconda sezione, solo i primi 15 elementi della raccolta sottostante sono enumerati su
Penso che la seconda è IMHO più leggibile – JoshBerke
Cosa c'è di enumerazione()? – BFree
Puoi fornirci un breve riepilogo di quale sia il tuo obiettivo con la funzione Sezione? Sembra che tu stia tentando di prendere un IEnumerable e di enumerare su di esso ottenendo un nuovo IEnumerable con elementi di lunghezza ogni volta, giusto? – JoshBerke