Массив ломтиков в C # - PullRequest
197 голосов
/ 02 января 2009

Как ты это делаешь? Дан байтовый массив:

byte[] foo = new byte[4096];

Как получить первые байты массива в виде отдельного массива? (В частности, мне нужно это как IEnumerable<byte>)

Это для работы с Socket с. Я полагаю, что самым простым способом было бы нарезать массив, аналогично синтаксису Perls:

@bar = @foo[0..40];

Что вернет первые 41 элемент в массив @bar. Есть ли в C # что-то, чего мне просто не хватает, или есть что-то, что я должен делать?

LINQ - вариант для меня (.NET 3.5), если это поможет.

Ответы [ 18 ]

192 голосов
/ 02 января 2009

Вы можете использовать ArraySegment<T>. Он очень легкий, так как не копирует массив:

string[] a = { "one", "two", "three", "four", "five" };
var segment = new ArraySegment<string>( a, 1, 2 );
173 голосов
/ 02 января 2009

Массивы перечислимы, поэтому ваш foo уже сам по себе IEnumerable<byte>. Просто используйте методы последовательности LINQ, такие как Take(), чтобы получить из этого то, что вы хотите (не забудьте включить пространство имен Linq с using System.Linq;):

byte[] foo = new byte[4096];

var bar = foo.Take(41);

Если вам действительно нужен массив из любого значения IEnumerable<byte>, вы можете использовать для этого метод ToArray(). Похоже, это не так.

116 голосов
/ 02 января 2009

Вы можете использовать метод массива CopyTo().

Или с LINQ вы можете использовать Skip() и Take() ...

byte[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
var subset = arr.Skip(2).Take(2);
51 голосов
/ 02 января 2009
static byte[] SliceMe(byte[] source, int length)
{
    byte[] destfoo = new byte[length];
    Array.Copy(source, 0, destfoo, 0, length);
    return destfoo;
}

//

var myslice = SliceMe(sourcearray,41);
16 голосов
/ 24 сентября 2010

Другая возможность, о которой я не упоминал, упоминается здесь: Buffer.BlockCopy () немного быстрее, чем Array.Copy (), и имеет дополнительное преимущество, заключающееся в возможности конвертировать на лету из массива примитивов ( скажем, короткий []) к массиву байтов, который может быть полезен, когда у вас есть числовые массивы, которые нужно передавать через сокеты.

14 голосов
/ 31 августа 2012

Вот простой метод расширения, который возвращает срез в виде нового массива:

public static T[] Slice<T>(this T[] arr, uint indexFrom, uint indexTo) {
    if (indexFrom > indexTo) {
        throw new ArgumentOutOfRangeException("indexFrom is bigger than indexTo!");
    }

    uint length = indexTo - indexFrom;
    T[] result = new T[length];
    Array.Copy(arr, indexFrom, result, 0, length);

    return result;
}

Тогда вы можете использовать его как:

byte[] slice = foo.Slice(0, 40);
13 голосов
/ 18 апреля 2018

В C # 7.2 , вы можете использовать Span<T>. Преимущество новой системы System.Memory заключается в том, что ей не нужно копировать данные.

Метод, который вам нужен: Slice:

Span<byte> slice = foo.Slice(0, 40);

Многие методы теперь поддерживают Span и IReadOnlySpan, поэтому будет очень просто использовать этот новый тип.

Обратите внимание, что на момент написания статьи тип Span<T> еще не определен в самой последней версии .NET (4.7.1), поэтому для его использования необходимо установить пакет System.Memory от NuGet.

13 голосов
/ 02 января 2009

Если хотите IEnumerable<byte>, то просто

IEnumerable<byte> data = foo.Take(x);
12 голосов
/ 03 апреля 2019

Начиная с C # 8.0

Будет поддерживаться срез массива, а также добавляются новые типы Index и Range.

Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"

var slice = a[i1..i2]; // { 3, 4, 5 }

префикс ^ указывает счет от end массива.

Пример кода выше, взятый из блога C # 8.0 .

Range и Index также работают с циклами foreach

Range range = 1..4; 
foreach (var name in names[range])

Перебирает записи с 1 по 4


обратите внимание, что на момент написания этого ответа C # 8.0 еще не был официально выпущен

8 голосов
/ 12 июня 2015

Если вы не хотите добавлять LINQ или другие расширения, просто выполните:

float[] subArray = new List<float>(myArray).GetRange(0, 8).ToArray();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...