我有一个数组,其中包含以下格式的数据结构字段;
[0] = Record 1 (Name Field)
[1] = Record 1 (ID Field)
[2] = Record 1 (Other Field)
[3] = Record 2 (Name Field)
[4] = Record 2 (ID Field)
[5] = Record 2 (Other Field)
等等
我正在将其处理成一个集合,如下所示;
for (int i = 0; i < components.Length; i = i + 3)
{
results.Add(new MyObj
{
Name = components[i],
Id = components[i + 1],
Other = components[i + 2],
});
}
这工作正常,但我想知道是否有一种很好的方法可以使用 LINQ 实现相同的输出?这里没有功能需求,我只是好奇能不能做。
我确实做了一些按索引分组的实验(在 ToList() 数组之后);
var groupings = components
.GroupBy(x => components.IndexOf(x) / 3)
.Select(g => g.ToArray())
.Select(a => new
{
Name = a[0],
Id = a[1],
Other = a[2]
});
这行得通,但我认为这对于我正在尝试做的事情来说有点矫枉过正。有没有更简单的方法来实现与 for 循环相同的输出?
请您参考如下方法:
看起来是乔什·爱因斯坦的 IEnumerable.Batch 的完美候选人扩大。它将可枚举的对象切成一定大小的 block ,并将它们作为数组的枚举提供:
public static IEnumerable<T[]> Batch<T>(this IEnumerable<T> self, int batchSize)
在这个问题的情况下,你会做这样的事情:
var results =
from batch in components.Batch(3)
select new MyObj { Name = batch[0], Id = batch[1], Other = batch[2] };
更新:2 年过去了,我链接到的 Batch 扩展似乎已经消失了。由于它被认为是问题的答案,并且以防万一其他人发现它有用,这里是我当前对 Batch 的实现:
public static partial class EnumExts
{
/// <summary>Split sequence into blocks of specified size.</summary>
/// <typeparam name="T">Type of items in sequence</typeparam>
/// <param name="sequence"><see cref="IEnumerable{T}"/> sequence to split</param>
/// <param name="batchLength">Number of items per returned array</param>
/// <returns>Arrays of <paramref name="batchLength"/> items, with last array smaller if sequence count is not a multiple of <paramref name="batchLength"/></returns>
public static IEnumerable<T[]> Batch<T>(this IEnumerable<T> sequence, int batchLength)
{
if (sequence == null)
throw new ArgumentNullException("sequence");
if (batchLength < 2)
throw new ArgumentException("Batch length must be at least 2", "batchLength");
using (var iter = sequence.GetEnumerator())
{
var bfr = new T[batchLength];
while (true)
{
for (int i = 0; i < batchLength; i++)
{
if (!iter.MoveNext())
{
if (i == 0)
yield break;
Array.Resize(ref bfr, i);
break;
}
bfr[i] = iter.Current;
}
yield return bfr;
bfr = new T[batchLength];
}
}
}
}
此操作是延迟的、单一枚举并在线性时间内执行。与我见过的其他一些 Batch 实现相比,它相对较快,即使它为每个结果分配一个新数组也是如此。
这只是表明:在分析之前您永远无法分辨,并且您应该始终引用代码以防它消失。
