SplitUp()
This SplitUp() extension method takes a sequence and splits it up into subsequences that each have a maximum length. See http://peshir.blogspot.nl/2011/02/example-of-c-lazy-functional.html for more information.
Source
namespace peSHIr.Utilities
{
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
/// <summary>Utility code for working with sequences</summary>
public static class SequenceUtility
{
/// <summary>Split up sequence of items</summary>
/// <typeparam name="T">Item type</typeparam>
/// <param name="input">Input sequence</param>
/// <param name="n">Maximum number of items per sublists</param>
/// <returns>Sequence of lists with a maximum
/// of <paramref name="n"/> items</returns>
/// <remarks>Might need a suppression of code analysis rule
/// CA1006 because of the nested generic type in the method
/// signature.</remarks>
public static IEnumerable<IEnumerable<T>>
SplitUp<T>(this IEnumerable<T> input, int n)
{
// Non-lazy error checking
if (input == null) throw new ArgumentNullException("input");
if (n < 1) throw new ArgumentOutOfRangeException("n", n, "<1");
return SplitUpLazy(input, n);
}
private static IEnumerable<IEnumerable<T>>
SplitUpLazy<T>(IEnumerable<T> input, int n)
{
// Lazy yield based implementation
var list = new List<T>();
foreach (T item in input)
{
list.Add(item);
if (list.Count == n)
{
yield return list;
list = new List<T>();
}
}
if (list.Count > 0) yield return list;
yield break;
}
}
}
Example
namespace SplitUpExample
{
using System;
using System.Linq;
using System.Collections.Generic;
using peSHIr.Utilities;
class Program
{
static bool TraceDataCreation;
static Action<string> println = text => Console.WriteLine(text);
static Action<string> print = text => Console.Write(text);
static Action newline = () => Console.WriteLine();
static void Main(string[] args)
{
newline();
println("* How can SplitUp() be used for paging");
TraceDataCreation = false;
var allData = TestData(64);
var pagedData = allData.SplitUp(7);
foreach (var page in pagedData)
{
print("Page:");
foreach (int i in page)
{
print(" ");
print(i.ToString());
}
newline();
}
newline();
println("* And is it really lazy?");
TraceDataCreation = true;
println("Calling SplitUp() on infinite sequence now");
var pagedInfinity = TestData().SplitUp(4);
println("Retrieving first page now");
var page1 = pagedInfinity.ElementAt(0);
println("Retrieving third page now");
var page3 = pagedInfinity.ElementAt(2);
Action<string,int,int> results = (text,sum,count)
=> Console.WriteLine("{0}: {1}, {2}", text, sum, count);
println("Showing results:");
results("First page", page1.Sum(), page1.Count());
results("Third page", page3.Sum(), page3.Count());
println("So yes, SplitUp() is lazy like LINQ! ;-)");
#if DEBUG
newline();
println("(Key to quit)");
Console.ReadKey();
#endif
}
static IEnumerable<int> TestData(int n)
{
return TestData().Take(n);
}
static IEnumerable<int> TestData()
{
// WARNING: this returns an infinite sequence!
// Or at least: until int overflows... ;-)
int i = 0;
while (true)
{
if (TraceDataCreation)
Console.WriteLine("Yielding {0}", i);
yield return i++;
}
}
}
}
Author: peSHIr
Submitted on: 6 mei 2014
Language: C#
Type: System.Collections.Generic.IEnumerable<T>
Views: 5135