Skip to content

Instantly share code, notes, and snippets.

@atifaziz
Created April 8, 2014 14:59
Show Gist options
  • Save atifaziz/10138114 to your computer and use it in GitHub Desktop.
Save atifaziz/10138114 to your computer and use it in GitHub Desktop.
LINQ operator to split a sequence into two based on a condition
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>());
}
}
@jabbalaci
Copy link

Usage example? Add one to see how to use it!

@mrseanryan
Copy link

Usage can be like this:

var (selected, notSelected) = myEnumerable.Partition(x => x > 10, (a, b) => (a, b));

@mrseanryan
Copy link

mrseanryan commented Dec 9, 2022

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>());
}

@mrseanryan
Copy link

Then usage would be like:

var (selected, notSelected) = myEnumerable.Partition(x => x > 10);

@atifaziz
Copy link
Author

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