Given a collection of items, how do I split the collection into 2 sub-collections based on a predicate?
You could do 2 Where searches, but then the run time is 2*N (which, while still O(n), takes twice as long and is obviously not preferred)
IEnumerable<int> even = nums.Where(i => IsEven(i));
IEnumerable<int> odd = nums.Where(i => !IsEven(i));
You could do a single linear pass yourself (refactored into an extension method here), but this means you have to drag this code all over, and more custom code makes things less maintainable.
public static void SplitOnPred<T>(
this IEnumerable<T> collection,
Func<T, bool> pred,
out IEnumerable<T> trueSet,
out IEnumerable<T> falseSet
) {
List<T> trueSetList = new List<T>();
List<T> falseSetList = new List<T>();
foreach( T item in collection ) {
if( pred( item ) ) {
trueSetList.Add( item );
} else {
falseSetList.Add( item );
}
}
trueSet = trueSetList;
falseSet = falseSetList;
}
Question:
Does LINQ have any native support for splitting a collection in 1 linear pass?
There are no built-in methods that split a collection into two versions based on a predicate. You would need to use your own method, similar to the one you posted.
The closest built-in method would be
GroupBy(orToLookup). You could group by odd or even:This will split into two “groups” based on whether the numbers are odd or even.