【发布时间】:2018-05-20 20:39:34
【问题描述】:
我正在寻找将数组拆分为固定大小块的最快方法(当然,最后一个可以更小)。我浏览了整个网站,没有发现任何性能方面的比较,所以我写了它们,结果如下:
以微秒为单位的时间,平均值/错误/标准差
对于
int[]- 30.02 | 0.1002 | 0.0937对于
IEnumerable<int>- 76.67 | 0.2146 | 0.1902
更新:以下版本(在@Markus 的回答中)是 139.5 | 0.6702 | 0.5597
在 SO 上最受欢迎且经常推荐使用 LINQ 的 GroupBy 和 index/chunkSize 的方法是不行的 - 267 微秒比上述任何一种实现都长得多。
有没有更快的分割数组的方法?
附:
这是Array 和IEnumerable<T> 的代码:
/// <summary>
/// Splits <paramref name="source"/> into chunks of size not greater than <paramref name="chunkMaxSize"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">Array to be split</param>
/// <param name="chunkMaxSize">Max size of chunk</param>
/// <returns><see cref="IEnumerable{T}"/> of <see cref="Array"/> of <typeparam name="T"/></returns>
public static IEnumerable<T[]> AsChunks<T>(this T[] source, int chunkMaxSize)
{
var pos = 0;
var sourceLength = source.Length;
do
{
var len = Math.Min(pos + chunkMaxSize, sourceLength) - pos;
if (len == 0)
{
yield break;;
}
var arr = new T[len];
Array.Copy(source, pos, arr, 0, len);
pos += len;
yield return arr;
} while (pos < sourceLength);
}
/// <summary>
/// Splits <paramref name="source"/> into chunks of size not greater than <paramref name="chunkMaxSize"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"><see cref="IEnumerable{T}"/> to be split</param>
/// <param name="chunkMaxSize">Max size of chunk</param>
/// <returns><see cref="IEnumerable{T}"/> of <see cref="Array"/> of <typeparam name="T"/></returns>
public static IEnumerable<T[]> AsChunks<T>(this IEnumerable<T> source, int chunkMaxSize)
{
var arr = new T[chunkMaxSize];
var pos = 0;
foreach (var item in source)
{
arr[pos++] = item;
if (pos == chunkMaxSize)
{
yield return arr;
arr = new T[chunkMaxSize];
pos = 0;
}
}
if (pos > 0)
{
Array.Resize(ref arr, pos);
yield return arr;
}
}
P.P.S 带有 BenchmarkDotNet 测试的完整解决方案是 on GitHub。
【问题讨论】:
-
Span<T>来了。 -
@ErikPhilips,这是一件坏事吗?如果实现起来既快速又容易——为什么还要坚持缓慢的实现呢?
-
@mjwills 基于 LINQ 的速度非常慢,我怀疑这个会更快。将添加到测试并更新问题。
-
@ErikPhilips 您对一般优先级的看法是正确的,但总有一个“但是”,对吧?尽管您可能不了解我的需求,但如果可以在其他地方讨论这些主题,我将不胜感激。我请求了其他程序员的帮助,仅此而已。
标签: c# .net arrays performance