C# LINQ本机是否支持将集合一分为二?

C# LINQ本机是否支持将集合一分为二?,c#,linq,C#,Linq,给定一个项目集合,如何基于谓词将集合拆分为两个子集合 您可以在其中执行2次搜索,但运行时间是2*N(虽然仍然是O(N),但需要两倍的时间,这显然不是首选) IEnumerable偶数=nums.Where(i=>IsEven(i)); IEnumerable奇数=nums.Where(i=>!IsEven(i)); 您可以自己进行一次线性传递(这里重构为一个扩展方法),但这意味着您必须将此代码拖到所有地方,更多自定义代码会降低可维护性 public static void SplitOnPre

给定一个项目集合,如何基于谓词将集合拆分为两个子集合

您可以在其中执行2次搜索,但运行时间是2*N(虽然仍然是O(N),但需要两倍的时间,这显然不是首选)

IEnumerable偶数=nums.Where(i=>IsEven(i));
IEnumerable奇数=nums.Where(i=>!IsEven(i));
您可以自己进行一次线性传递(这里重构为一个扩展方法),但这意味着您必须将此代码拖到所有地方,更多自定义代码会降低可维护性

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;
}
公共静态void SplitOnPred(
这是数不清的收藏,
Func pred,
输出IEnumerable Truset,
不可数假集
) {
List trueSetList=新列表();
List falseSetList=新列表();
foreach(集合中的T项){
if(预测(项目)){
trueSetList.Add(项);
}否则{
falseSetList.添加(项目);
}
}
trueSet=trueSetList;
falseSet=falseSetList;
}
问题: LINQ是否支持在一个线性过程中拆分集合

LINQ是否支持在一个线性过程中拆分集合

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

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

var groups = nums.GroupBy(i => IsEven(i));

这将根据数字是奇数还是偶数分为两个“组”。

如果逻辑是封闭的,在您的情况下,您可以这样做

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

里德·科佩的回答提到了托卢库普,这似乎很吸引人

var lookup = nums.ToLookup(IsEven);
其中,
IsEven
是一个具有预期签名和返回类型的静态方法。然后

IEnumerable<int> even = lookup[true];
IEnumerable<int> odd = lookup[false];
IEnumerable偶数=查找[true];
IEnumerable奇数=查找[假];

如果要支持延迟执行,请使用以下函数或扩展:

IEnumerable<T> Split<T>(this IEnumerable<T> source, out IEnumerable<T> odd)
{
   IList<T> oddCollector = new List<T>();
   Bool odd = true;
   foreach(T item in source)
   {
      if(odd)
      {
          oddCollector.Add(item);
      }
      else
      {
          yield return item;
      }
      odd = !odd;
   }
 }
IEnumerable拆分(此IEnumerable源,输出IEnumerable奇数)
{
IList oddCollector=新列表();
布尔奇数=真;
foreach(源中的T项)
{
if(奇数)
{
添加(项目);
}
其他的
{
收益回报项目;
}
奇数=!奇数;
}
}

对于任何一个小小的编译器错误,我深表歉意,我是发自内心地这么做的。您可以添加谓词,而不是偶数/奇数。

为什么需要一条线性路径?@SaeedAmiri这不是一个真正的要求,在大多数情况下,两条线性路径足够好,但我对足够好的性能从来没有真正满意过:p警告这只支持延迟执行,如果您先读取偶数,或者以交替顺序读取两个枚举数。如果你先读奇数,你不会得到所有的结果。
IEnumerable<int> even = lookup[true];
IEnumerable<int> odd = lookup[false];
IEnumerable<T> Split<T>(this IEnumerable<T> source, out IEnumerable<T> odd)
{
   IList<T> oddCollector = new List<T>();
   Bool odd = true;
   foreach(T item in source)
   {
      if(odd)
      {
          oddCollector.Add(item);
      }
      else
      {
          yield return item;
      }
      odd = !odd;
   }
 }