Skip to content

Instantly share code, notes, and snippets.

@Dkowald
Created September 12, 2012 01:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dkowald/3703440 to your computer and use it in GitHub Desktop.
Save Dkowald/3703440 to your computer and use it in GitHub Desktop.
.NET generic Split<T>() extension
namespace derek.kowald.util
{
public static class IEnumerableExtension
{
/// <summary>
/// Generic split operation, behave the same as string split.
/// </summary>
/// <remarks>
/// Other usefull split options, such as count and remove empty from string.split()
/// are better implemented with a little linq code:
/// .Take(n) and .Where(l => l.Any()) respectivly.
/// </remarks>
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, Predicate<T> seperator)
{
if (seperator == null)
{ throw new ArgumentNullException("seperator"); }
//loop each.
if (source != null && source.Any())
{
var next = new List<T>();
foreach (var item in source)
{
if (seperator(item))
{
yield return next;
next = new List<T>();
}
else
{
next.Add(item);
}
}
yield return next;
}
//xplicit empty enumeration (rahter than the confusing no-return option).
yield break;
}
}
}
namespace derek.kowald.test.util
{
[TestClass]
public class IEnumerableExtensionTest
{
[TestMethod]
public void Split_MultiLine()
{
var data = ("A Line\nthe next line\n\n").ToList();
var lines = data.Split(c => { return c == '\n'; }).ToList();
Assert.AreEqual(4, lines.Count, "just like string split, an ending seperator is an empty last line.");
}
[TestMethod]
public void Split_RemovesSeperator()
{
var data = "A line \n";
var lines = data.Split(c => c == '\n');
Assert.AreNotEqual('\n', lines.First().Last(), "ending new-line is striped.");
}
[TestMethod]
public void Split_EndsWithSeperator()
{
var data = "A Single line\n".ToList();
var lines = data.Split(c => c == '\n');
Assert.AreEqual(2, lines.Count(), "ending seperator indicates a empty last line, same as string.split");
}
[TestMethod]
public void Split_NoSeperator()
{
var data = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var lines = data.Split(i => i == 0);
Assert.AreEqual(1, lines.Count());
}
[TestMethod]
public void Split_SeqOfSeperator()
{
var data = "Multi \n\n\n Seperators\n".ToList();
var lines = data.Split(c => c =='\n');
Assert.AreEqual(5, lines.Count());
}
[TestMethod]
public void Split_EmptyLine_IsEmptyList()
{
var data = "\n\n".ToList();
var lines = data.Split(c => c == '\n').ToList();
Assert.AreEqual(3, lines.Count());
Assert.IsNotNull(lines.First());
Assert.AreEqual(0, lines.First().Count());
}
[TestMethod]
public void Split_NullOrEmptySource()
{
IEnumerable<int> nullData = null;
var emptyData = String.Empty.ToList();
var nullLines = nullData.Split(i => i < 0);
var emptyLines = emptyData.Split(c => c == '\n');
Assert.AreEqual(0, nullLines.Count());
Assert.AreEqual(0, emptyLines.Count());
}
[TestMethod]
public void Split_NoPredicate()
{
var data = "some sample data.".ToList();
Exception error = null;
try
{
var lines = data.Split(null).ToList();
}
catch (ArgumentNullException ex)
{
error = ex;
}
Assert.IsNotNull(error, "null pred, cause error.");
}
[TestMethod]
public void Split_PredThrows()
{
var data = new[] { 3, 5, 6, 2, 6, 4 };
ApplicationException error = null;
try
{
data.Split(i =>
{
if (i == 6)throw new ApplicationException("broken");
return false;
}).ToList();
}
catch (ApplicationException ex)
{
error = ex;
}
Assert.IsNotNull(error, "just passes out the predicate error.");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment