如何通过 Linq 将集合拆成多个块?

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何通过 Linq 将集合拆成多个块?相关的知识,希望对你有一定的参考价值。

咨询区

  • BlakeH

请问是否可以用 linq 按序生成带有多个固定 size 的块?我的理想情况下还可以对这些 进行操作。

回答区

  • Sergey Berezovskiy

说实话,你不需要写任何代码,使用 MoreLINQ 中的批次方法即可,它可以按序拆解到固定大小的桶中,你可以直接在 Nuget 上安装 MoreLINQ 包。

int size = 10;
var batches = sequence.Batch(size);

如果你好奇它的实现方法,可参考如下源码:

public static IEnumerable<IEnumerable<TSource>> Batch<TSource>(
                  this IEnumerable<TSource> source, int size)

    TSource[] bucket = null;
    var count = 0;

    foreach (var item in source)
    
        if (bucket == null)
            bucket = new TSource[size];

        bucket[count++] = item;
        if (count != size)
            continue;

        yield return bucket;

        bucket = null;
        count = 0;
    

    if (bucket != null && count > 0)
        yield return bucket.Take(count).ToArray();
  • dana

这个需求确实比较常见,在 .NET6 中添加了一个 Enumerable.Chunk() 扩展方法,然后你就可以像下面这样使用。

var list = new List<int>  1, 2, 3, 4, 5, 6, 7 ;

var chunks = list.Chunk(3);
// returns   1, 2, 3 ,  4, 5, 6 ,  7  

如果你对源码感兴趣,可以参考如下:

public static IEnumerable<TSource[]> Chunk<TSource>(this IEnumerable<TSource> source, int size)

 if (source == null)
 
  ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
 
 if (size < 1)
 
  ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.size);
 
 return ChunkIterator(source, size);


private static IEnumerable<TSource[]> ChunkIterator<TSource>(IEnumerable<TSource> source, int size)

 using IEnumerator<TSource> e = source.GetEnumerator();
 while (e.MoveNext())
 
  TSource[] array = new TSource[size];
  array[0] = e.Current;
  int i;
  for (i = 1; i < array.Length; i++)
  
   if (!e.MoveNext())
   
    break;
   
   array[i] = e.Current;
  
  if (i == array.Length)
  
   yield return array;
   continue;
  
  Array.Resize(ref array, i);
  yield return array;
  break;
 

点评区

发现 .NET6 下的 Enumerable 增加了一些 By 系列方法:MinBy,ExceptBy,IntersectBy,又有得学了。

以上是关于如何通过 Linq 将集合拆成多个块?的主要内容,如果未能解决你的问题,请参考以下文章

LINQ to XML - 从文件加载 XML 片段

通过LINQ将函数应用于集合的所有元素[重复]

如何正确地将多个片段添加到片段过渡?

并行LINQ PLinq

OGG进程拆分(单表拆成多个进程)

控件集合无法修改,因为控件包含代码块(即 <% ... %>)