Как ты это делаешь? Дан байтовый массив:
byte[] foo = new byte[4096];
Как бы я получил первые х байтов массива в виде отдельного массива? (Конкретно мне это нужно как IEnumerable<byte>
)
Это для работы с Socket
с. Я полагаю, что самым простым способом было бы нарезать массив, аналогично синтаксису Perls:
@bar = @foo[0..40];
Который вернул бы первые 41 элемент в @bar
массив. Есть ли в C # что-то, чего мне просто не хватает, или есть что-то еще, что я должен делать?
LINQ - вариант для меня (.NET 3.5), если это поможет.
Ответы:
Массивы перечислимы, так что вы
foo
ужеIEnumerable<byte>
сами по себе. Просто используйте методы последовательности LINQ, например,Take()
чтобы получить то, что вы хотите из этого (не забудьте включитьLinq
пространство имен сusing System.Linq;
):Если вам действительно нужен массив из любого
IEnumerable<byte>
значения, вы можете использоватьToArray()
метод для этого. Это не похоже на случай здесь.источник
[2,3] => [1,1], [1,2], [1,3], [2,1], [2,2], [2,3]
. Зубчатые массивы также перечислимы, но вместо того, чтобы возвращать значение при перечислении, они возвращают свой внутренний массив. Как это:type[][] jaggedArray; foreach (type[] innerArray in jaggedArray) { }
IEnumerable<T>
», тогда мое заявление было бы более ясным. Смотрите также это: stackoverflow.com/questions/721882/…Вы могли бы использовать
ArraySegment<T>
. Он очень легкий, так как не копирует массив:источник
Вы можете использовать
CopyTo()
метод массивов .Или с LINQ вы можете использовать
Skip()
иTake()
...источник
Skip()
. ПростоTake()
не получу произвольный кусок. Кроме того, я все равно искал решение LINQ (часть IEnumerable, но я знал, что результаты по массиву будет легче найти).//
источник
Начиная с C # 8.0 / .Net Core 3.0
Будет поддерживаться нарезка массива,
Index
а такжеRange
добавляются новые типы .Range Struct docs
Индекс структурных документов
Выше пример кода взят из блога C # 8.0 .
обратите внимание, что
^
префикс указывает на отсчет с конца массива. Как показано в примере с документамиRange
аIndex
также работать вне нарезки массивов, например, с цикламиПеребирает записи с 1 по 4
обратите внимание, что на момент написания этого ответа C # 8.0 еще не был официально выпущенC # 8.x и .Net Core 3.x теперь доступны в Visual Studio 2019 и далее
источник
В C # 7.2 вы можете использовать
Span<T>
. Преимущество новойSystem.Memory
системы в том, что ей не нужно копировать данные.Метод, который вам нужен
Slice
:Многие методы теперь поддерживают
Span
иIReadOnlySpan
, поэтому будет очень просто использовать этот новый тип.Обратите внимание, что на момент написания этого
Span<T>
типа тип еще не был определен в самой последней версии .NET (4.7.1), поэтому для его использования необходимо установить пакет System.Memory из NuGet.источник
Span<T>
тип еще не определен в самой последней версии .Net (4.7.1), поэтому для его использования вам необходимо установитьSystem.Memory
из NuGet (и не забудьте поставить галочку «включить предварительный выпуск» при поиске его в NuGet)Еще одна возможность, о которой я не упомянул, упоминается здесь: Buffer.BlockCopy () немного быстрее, чем Array.Copy (), и имеет дополнительное преимущество, заключающееся в возможности преобразования на лету из массива примитивов (скажем, short []) к массиву байтов, который может быть полезен, когда у вас есть числовые массивы, которые нужно передавать через сокеты.
источник
Buffer.BlockCopy
дали разные результаты, чем приArray.Copy()
том, что они принимают одинаковые параметры - было много пустых элементов. Зачем?Array.Copy(array1, 0, array2, 0, 10)
, ноBuffer.BlockCopy(array1, 0, array2, 0, 10 * sizeof(int))
.Если хочешь
IEnumerable<byte>
, то простоисточник
Вот простой метод расширения, который возвращает срез в виде нового массива:
Тогда вы можете использовать его как:
источник
Если вы не хотите добавлять LINQ или другие расширения, просто сделайте:
источник
Error CS0246: The type or namespace name 'List<>' could not be found (are you missing a using directive or an assembly reference?)
Документация Microsoft безнадежна с сотнями проиндексированных записей «Списка». Что здесь правильно?System.Collections.Generic.List
Вы можете использовать обертку вокруг исходного массива (который является IList), как в этом (непроверенном) фрагменте кода.
}
источник
Array.Copy
, хотя это может иметь много преимуществ, таких как, например, SubList, являющийся регионом в родительском Списке, вместо копии записей в Списке.источник
Для байтовых массивов System.Buffer.BlockCopy обеспечит вам наилучшую производительность.
источник
Вы можете использовать метод расширения Take
источник
Это может быть решением, которое:
Тогда результатом является IEnumerable <IEnumerable <byte >> с первым IEnumerable <byte> содержит первые 40 байтов foo , а второй IEnumerable <byte> содержит остальные.
Я написал класс-обертку, вся итерация ленива, надеюсь, это поможет:
источник
Я не думаю, что C # поддерживает семантику Range. Вы можете написать метод расширения, например:
Но, как говорили другие, если вам не нужно устанавливать начальный индекс, тогда
Take
это все, что вам нужно.источник
Вот функция расширения, которая использует универсальный и ведет себя как PHP-функция array_slice . Отрицательное смещение и длина допускаются.
источник
start
не между 0 иarr.Length
, это, вероятно, должно генерировать исключение вне границ. Кроме того,end >= start >= 0
так что вам не нужно проверятьend < 0
, это не возможно, что это произойдет. Возможно, вы могли бы сделать это еще более кратко, проверив это,length >= 0
а затемlen = Math.min(length, arr.Length - start)
вместо того, чтобы возиться сend
.источник