您的位置:首页 > 其它

Stackoverflow 珠玑:用于分组的 LINQ 扩展方法

2017-04-03 02:24 555 查看
从 stackoverflow.com 上抄来的,将 IEnumerable 中的元素进行切分的方法,无动态内存分配,地球上最快的实现:

public static class LinqExtensions
{
/// <summary>
/// 将 source 中的条目按照 partitionSize 指定的每组数量进行分组
/// http://stackoverflow.com/questions/3773403/linq-partition-list-into-lists-of-8-members /// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="partitionSize"></param>
/// <returns></returns>
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> source, int partitionSize)
{
if (partitionSize <= 0)
{
throw new ArgumentOutOfRangeException(nameof(partitionSize));
}

int innerListCounter = 0;
int numberOfPackets = 0;
foreach (var item in source)
{
innerListCounter++;
if (innerListCounter == partitionSize)
{
yield return source.Skip(numberOfPackets * partitionSize).Take(partitionSize);
innerListCounter = 0;
numberOfPackets++;
}
}

if (innerListCounter > 0)
{
yield return source.Skip(numberOfPackets * partitionSize);
}
}

/// <summary>
/// 将 source 中的条目按照 numberOfChunks 参数指定的分组数进行切分
/// http://stackoverflow.com/questions/438188/split-a-collection-into-n-parts-with-linq/13744322#13744322 /// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="numberOfChunks"></param>
/// <returns></returns>
public static IEnumerable<IEnumerable<T>> Split<T>(this ICollection<T> source, int numberOfChunks)
{
if (numberOfChunks <= 0 || numberOfChunks > source.Count)
{
throw new ArgumentOutOfRangeException(nameof(numberOfChunks));
}

int sizePerPacket = source.Count / numberOfChunks;
int extra = source.Count % numberOfChunks;

for (int i = 0; i < numberOfChunks - extra; i++)
{
yield return source.Skip(i * sizePerPacket).Take(sizePerPacket);
}

int alreadyReturnedCount = (numberOfChunks - extra) * sizePerPacket;
int toReturnCount = extra == 0 ? 0 : (source.Count - numberOfChunks) / extra + 1;
for (int i = 0; i < extra; i++)
{
yield return source.Skip(alreadyReturnedCount + i * toReturnCount).Take(toReturnCount);
}
}

}


两个方法以不同的形式对 IEnumerable 集合中的元素进行分组,非常有用,而且没有容器操作等动态内存分配,不可能再快了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐