listOfByteArrs.SelectMany(byteArr=>byteArr).ToArray()
Приведенный выше код объединит последовательность последовательностей байтов в одну последовательность и сохранит результат в массиве.
Несмотря на то, что он читаем, он не максимально эффективен - он не используеттот факт, что вы уже знаете длину результирующего байтового массива и, таким образом, можете избежать динамически расширенной реализации .ToArray()
, которая обязательно включает в себя несколько выделений и копий массива.Кроме того, SelectMany
реализовано в терминах итераторов;это означает много + много интерфейсных вызовов, что довольно медленно.Однако для небольших наборов данных это вряд ли имеет значение.
Если вам нужна более быстрая реализация, вы можете сделать следующее:
var output = new byte[listOfByteArrs.Sum(arr=>arr.Length)];
int writeIdx=0;
foreach(var byteArr in listOfByteArrs) {
byteArr.CopyTo(output, writeIdx);
writeIdx += byteArr.Length;
}
иликак предлагает Мартиньо:
var output = new byte[listOfByteArrs.Sum(arr => arr.Length)];
using(var stream = new MemoryStream(output))
foreach (var bytes in listOfByteArrs)
stream.Write(bytes, 0, bytes.Length);
Некоторые временные значения:
var listOfByteArrs = Enumerable.Range(1,1000)
.Select(i=>Enumerable.Range(0,i).Select(x=>(byte)x).ToArray()).ToList();
Использование метода short для объединения этих 500500 байт занимает 15 мс, использование быстрого метода на моей машине занимает 0,5 мс - YMMVи обратите внимание, что для многих приложений и то, и другое более чем достаточно; -).
Наконец, вы можете заменить Array.CopyTo
на static
Array.Copy
, низкоуровневый Buffer.BlockCopy
или MemoryStream
с предварительно выделенным задним буфером - все они работают примерно одинаково в моих тестах (x64 .NET 4.0).