LINQ本身是否支持将一个集合拆分为两个?

Jam*_*mes 29 c# linq

给定项目集合,如何根据谓词将集合拆分为2个子集合?

您可以进行2次搜索,但运行时间为2*N(虽然仍为O(n),但需要两倍的时间,显然不是首选)

IEnumerable<int> even = nums.Where(i => IsEven(i));
IEnumerable<int> odd = nums.Where(i => !IsEven(i));
Run Code Online (Sandbox Code Playgroud)

你可以自己做一个线性传递(在这里重构为扩展方法),但这意味着你必须全部拖动这些代码,而更多的自定义代码使得事情的可维护性降低.

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;
}
Run Code Online (Sandbox Code Playgroud)

问题: LINQ是否有任何原生支持在1个线性传递中拆分集合?

Ree*_*sey 28

LINQ是否有任何原生支持在1个线性传递中拆分集合?

没有内置方法可以根据谓词将集合拆分为两个版本.您需要使用自己的方法,类似于您发布的方法.

最接近的内置方法是GroupBy(或ToLookup).您可以按奇数或偶数分组:

var groups = nums.GroupBy(i => IsEven(i));
Run Code Online (Sandbox Code Playgroud)

根据数字是奇数还是偶数,这将分成两个"组".


Jep*_*sen 11

Reed Copsey的回答提到ToLookup,这似乎很有吸引力.

var lookup = nums.ToLookup(IsEven);
Run Code Online (Sandbox Code Playgroud)

其中IsEven是具有预期签名和返回类型的静态方法.然后

IEnumerable<int> even = lookup[true];
IEnumerable<int> odd = lookup[false];
Run Code Online (Sandbox Code Playgroud)


Tig*_*ran 5

如果逻辑是确凿的,在你的情况下,你可以这样做

var list = new List<int> {1,2,3,4,5,6,7,8,9,10};    
var result = list.GroupBy(x=> x%2==0);
Run Code Online (Sandbox Code Playgroud)

并在 result

foreach(var r in result)
{
    if(r.Key)
     //EVEN
    else 
     //ODD
}
Run Code Online (Sandbox Code Playgroud)