Created
April 8, 2014 14:59
-
-
Save atifaziz/10138114 to your computer and use it in GitHub Desktop.
LINQ operator to split a sequence into two based on a condition
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
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
static partial class Sequence | |
{ | |
/// <summary> | |
/// Splits the sequence into two sequences, containing the elements | |
/// for which the given predicate returns <c>true</c> and <c>false</c> | |
/// respectively. | |
/// </summary> | |
public static TResult Partition<T, TResult>(this IEnumerable<T> source, | |
Func<T, bool> predicate, | |
Func<IEnumerable<T>, IEnumerable<T>, TResult> selector) | |
{ | |
if (source == null) throw new ArgumentNullException("source"); | |
if (predicate == null) throw new ArgumentNullException("predicate"); | |
if (selector == null) throw new ArgumentNullException("selector"); | |
IEnumerable<T> fs = null; | |
IEnumerable<T> ts = null; | |
foreach (var g in source.GroupBy(predicate)) | |
{ | |
if (g.Key) | |
{ | |
Debug.Assert(ts == null); | |
ts = g; | |
} | |
else | |
{ | |
Debug.Assert(fs == null); | |
fs = g; | |
} | |
} | |
return selector(fs ?? Enumerable.Empty<T>(), | |
ts ?? Enumerable.Empty<T>()); | |
} | |
} |
Usage can be like this:
var (selected, notSelected) = myEnumerable.Partition(x => x > 10, (a, b) => (a, b));
Nice code - could it be simplified a bit:
(IEnumerable<T> selected, IEnumerable<T> notSelected) PartitionBy<T>(IEnumerable<T> items, Func<T, bool> predicate)
{
IEnumerable<T> selected = null;
IEnumerable<T> notSelected = null;
foreach (var g in items.GroupBy(predicate))
{
if (g.Key)
{
selected = g;
}
else
{
notSelected = g;
}
}
return (selected ?? Enumerable.Empty<T>(),
notSelected ?? Enumerable.Empty<T>());
}
Then usage would be like:
var (selected, notSelected) = myEnumerable.Partition(x => x > 10);
This is now added to MoreLINQ. Examples can be found in the doc, tests and original PR.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage example? Add one to see how to use it!