Created
January 23, 2020 14:46
-
-
Save pcrockett-pathway/5ba2fbbe9366933c3373c1900d5e1efe to your computer and use it in GitHub Desktop.
LINQ-like extension method for iterating over pairs of items
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// <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()); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [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