You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用LINQ同时返回满足/不满足比较器条件的两个IEnumerable?

解答

原生LINQ没有提供开箱即用的直接拆分两个序列的方法,但有两个非常实用的实现方案,都能满足你的需求,其中第一种性能最好,只会遍历一次源数据。

  • 方案1:自定义扩展方法(生产环境推荐)
    自己写个通用的拆分扩展方法是最常用的做法,单次遍历就能完成分组,不会有重复遍历的开销,代码也很简单:

    // 把这个静态方法放到你项目里任意一个静态工具类中即可全局调用
    public static (IEnumerable<T> Passed, IEnumerable<T> Failed) SplitBy<T>(
        this IEnumerable<T> source, 
        Func<T, bool> predicate)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        if (predicate == null) throw new ArgumentNullException(nameof(predicate));
        
        var passList = new List<T>();
        var failList = new List<T>();
        foreach (var item in source)
        {
            if (predicate(item))
                passList.Add(item);
            else
                failList.Add(item);
        }
        return (passList, failList);
    }
    

    你题目里待补充的代码直接调用这个扩展就行:

    var (listWhereTrue, listWhereFalse) = numbers.SplitBy(comparator);
    

    运行结果和预期完全一致:listWhereTrue 包含 0、1、2,listWhereFalse 包含3、4、5。

  • 方案2:用内置ToLookup方法临时实现
    要是只是写个临时脚本、不想额外加扩展方法,直接用LINQ内置的ToLookup就能实现,同样只遍历一次源序列:

    var groups = numbers.ToLookup(comparator);
    // 直接解构赋值的写法如下
    var (listWhereTrue, listWhereFalse) = (groups[true].ToList(), groups[false].ToList());
    

    这个方法返回的是分组查询结果,如果不需要立刻转成实体列表,去掉.ToList()也可以直接用。

避坑提示:别图省事写两次Where分别筛选,也就是分别写numbers.Where(comparator)和numbers.Where(x => !comparator(x)),这种写法会把源序列遍历两遍,数据量大的时候性能差很多,如果遍历过程有副作用逻辑还会出意料之外的bug。

内容的提问来源于stack exchange,提问作者user18908005

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:36:23