Skip to content

Instantly share code, notes, and snippets.

@pcrockett-pathway
Created January 23, 2020 14:46
Show Gist options
  • Select an option

  • Save pcrockett-pathway/5ba2fbbe9366933c3373c1900d5e1efe to your computer and use it in GitHub Desktop.

Select an option

Save pcrockett-pathway/5ba2fbbe9366933c3373c1900d5e1efe to your computer and use it in GitHub Desktop.
LINQ-like extension method for iterating over pairs of items
/// <summary>
/// Pairs adjacent items in an IEnumerable and executes a selector delegate on the two items together.
/// Returns an IEnumerable that contains one fewer item than the original.
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="source"></param>
/// <param name="pairFunc"></param>
/// <returns></returns>
public static IEnumerable<TResult> MakePairs<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> pairFunc)
{
if (source == null)
throw new ArgumentNullException(nameof(source), $"{nameof(source)} is null.");
if (pairFunc == null)
throw new ArgumentNullException(nameof(pairFunc), $"{nameof(pairFunc)} is null.");
using (var enumerator = source.GetEnumerator())
{
if (!enumerator.MoveNext())
throw new InvalidOperationException("Sequence is empty. It must contain at least 2 items.");
var prevItem = enumerator.Current;
if (!enumerator.MoveNext())
throw new InvalidOperationException("Sequence has only 1 item. It must contain at least 2 items.");
do
{
yield return pairFunc(prevItem, enumerator.Current);
prevItem = enumerator.Current;
} while (enumerator.MoveNext());
}
}
[Test]
public void MakePairs_EmptyCollection_ThrowsException()
{
var items = new int[0];
Assert.That(() => items.MakePairs((a, b) => "whatever").ToArray(),
Throws.InstanceOf<InvalidOperationException>());
}
[Test]
public void MakePairs_SingleItem_ThrowsException()
{
var items = new[] { 123 };
Assert.That(() => items.MakePairs((a, b) => "whatever").ToArray(),
Throws.InstanceOf<InvalidOperationException>());
}
[Test]
public void MakePairs_ThreeElements_Works()
{
var items = new[] { 1, 2, 3 };
var paired = items.MakePairs((a, b) => $"{a} and {b}").ToArray();
var expected = new[] { "1 and 2", "2 and 3" };
Assert.That(paired, Is.EqualTo(expected));
}
[Test]
public void MakePairs_Always_IsLazy()
{
var wasEvaluated = false;
var items = new[] { 1, 2, 3 };
var pairedLazy = items.MakePairs((a, b) =>
{
wasEvaluated = true;
return $"{a} and {b}";
});
Assert.That(wasEvaluated, Is.False);
pairedLazy.ToArray();
Assert.That(wasEvaluated, Is.True);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment