Search code examples
linqpartitioning

LINQ equivalent of F# List.partition


Using LINQ, how do you partition an IEnumerable in a way equivalent to F#'s List.parition function? The result should be the source sequence partitioned into two sequences based the predicate, with the predicate evaluated once per source item.


Solution

  • Enumerable.ToLookup comes close.

    var l = new int[]{1,2,3,4,5};
    
    var split = l.ToLookup( i => i > 2);
    
    var a = split[true]; // 3,4,5
    var b = split[false]; // 1,2
    

    It's not too hard to wrap this in a function.

    public static (IEnumerable<TSource> Yeses, IEnumerable<TSource> Nos) Partition<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        //Null handling?
        var s = source.ToLookup(i => predicate(i));
        return (s[true], s[false]);
    }
    
    public static void Main(string[] args)
    {
        var l = new int[] { 1,2,3,4,5 };
    
        var s = Partition(l, i => { Console.WriteLine($"Called: {i}"); return i > 2;});
    
        Console.WriteLine(string.Join(",", s.Yeses));
        Console.WriteLine(string.Join(",", s.Nos));
    }
    
    Called: 1
    Called: 2
    Called: 3
    Called: 4
    Called: 5
    3,4,5
    1,2