2 |
|
using System.Collections.Generic; |
3 |
|
using System.Linq; |
4 |
|
using System.Text; |
5 |
+ |
using System.Diagnostics; |
6 |
|
|
7 |
|
namespace libxmltv |
8 |
|
{ |
29 |
|
|
30 |
|
public static class extensions |
31 |
|
{ |
32 |
< |
/// <summary> |
33 |
< |
/// Break a list of items into chunks of a specific size |
33 |
< |
/// </summary> |
34 |
< |
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int chunksize) |
32 |
> |
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, |
33 |
> |
int chunkSize) |
34 |
|
{ |
35 |
< |
while (source.Any()) |
35 |
> |
// Validate parameters. |
36 |
> |
if (source == null) throw new ArgumentNullException("source"); |
37 |
> |
if (chunkSize <= 0) throw new ArgumentOutOfRangeException("chunkSize", |
38 |
> |
"The chunkSize parameter must be a positive value."); |
39 |
> |
|
40 |
> |
// Call the internal implementation. |
41 |
> |
return source.ChunkInternal(chunkSize); |
42 |
> |
} |
43 |
> |
private static IEnumerable<IEnumerable<T>> ChunkInternal<T>(this IEnumerable<T> source, int chunkSize) |
44 |
> |
{ |
45 |
> |
// Validate parameters. |
46 |
> |
Debug.Assert(source != null); |
47 |
> |
Debug.Assert(chunkSize > 0); |
48 |
> |
|
49 |
> |
// Get the enumerator. Dispose of when done. |
50 |
> |
using (IEnumerator<T> enumerator = source.GetEnumerator()) |
51 |
> |
do |
52 |
> |
{ |
53 |
> |
// Move to the next element. If there's nothing left |
54 |
> |
// then get out. |
55 |
> |
if (!enumerator.MoveNext()) yield break; |
56 |
> |
|
57 |
> |
// Return the chunked sequence. |
58 |
> |
yield return ChunkSequence(enumerator, chunkSize); |
59 |
> |
} while (true); |
60 |
> |
} |
61 |
> |
private static IEnumerable<T> ChunkSequence<T>(IEnumerator<T> enumerator, int chunkSize) |
62 |
> |
{ |
63 |
> |
// Validate parameters. |
64 |
> |
Debug.Assert(enumerator != null); |
65 |
> |
Debug.Assert(chunkSize > 0); |
66 |
> |
|
67 |
> |
// The count. |
68 |
> |
int count = 0; |
69 |
> |
|
70 |
> |
// There is at least one item. Yield and then continue. |
71 |
> |
do |
72 |
|
{ |
73 |
< |
yield return source.Take(chunksize); |
74 |
< |
source = source.Skip(chunksize); |
75 |
< |
} |
73 |
> |
// Yield the item. |
74 |
> |
yield return enumerator.Current; |
75 |
> |
} while (++count < chunkSize && enumerator.MoveNext()); |
76 |
|
} |
77 |
|
} |
78 |
|
} |