Как строку 256 символов разбить на 8 блоков и поместить в массив uint?

Имеется строка 256 символов

ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff

Как ее разбить на 8 блоков и поместить в массив uint[]?


Ответы (1 шт):

Автор решения: VladD

Например, так:

Enumerable.Range(0, s.Length / 8)
          .Select(n => uint.Parse(s.AsSpan(n * 8, 8),
                                  NumberStyles.HexNumber,
                                  CultureInfo.InvariantCulture))
          .ToArray();

Объяснение:

Мы делим строку на блоки по 8 символов, всего таких блоков будет s.Length / 8. Enumerable.Range(0, s.Length / 8) выдаёт последовательность индексов от 0 do максимального.

Далее, для каждого индекса мы берём нужный блок. Для индекса n он начинается с позиции n * 8, т. к. длина каждого блока 8 символов, и имеет длину 8, поэтому нужная часть строки задаётся выражением s.AsSpan(n * 8, 8). (Для старых версий C# придётся использовать менее эффективный Substring, который аллоцирует новую строку-копию.)

Далее, полученный кусок надо распарсить как 16-ричное число. Для этого берём uint.Parse с соответствующими параметрами.

Получившуюся ленивую последовательность материализуем в массив при помощи .ToArray().

Всё!


P. S.: В будущих версиях .NET будет добавлен удобный метод Chunk, позволяющий «нарезать» последовательность на куски фиксированного размера, и можно будет написать изящнее:

s.Chunk(8)
 .Select(part => uint.Parse(part,
                            NumberStyles.HexNumber,
                            CultureInfo.InvariantCulture))
 .ToArray();

Впрочем, сейчас похожая функциональность есть в пакете morelinq под названием Batch.

P. P. S.: Поскольку новый System.Range не реализует интерфейс IEnumerable<T>, мне прошлось использовать более древний Enumerable.Range вместо (0..s.Length/8).Select...

→ Ссылка