Преобразование 8-битного списка в 32-битный целочисленный массив в Python - PullRequest
0 голосов
/ 05 июля 2018

что у меня есть:

textdata = "this is my test data"
DataArray = [ord(c) for c in textdata]

Теперь я хочу преобразовать это в 32-битное целое число, объединив 4 элемента списка вместе

Пример: DataArray [0: 4] станет 32-разрядным целым числом, а затем перейдет к следующим 4 элементам и сделает то же самое. В итоге у меня будет 32-битный массив со всеми моими результатами.

Как я могу сделать это в Python без перебора всей строки. Есть ли простой способ сделать это?

Ответы [ 4 ]

0 голосов
/ 05 июля 2018

Вы можете использовать встроенный модуль Python struct :

from struct import unpack

textdata = "this is my test data"
data = list(unpack('i'*(len(textdata)//4), textdata))

Результат:

[1936287860, 544434464, 1948285293, 544502629, 1635017060]

Вам не нужно будет перебирать строку, и вы можете найти другие Символы формата , если вы хотите использовать, например, целые числа без знака.

0 голосов
/ 05 июля 2018

Пока ваша строка кратна 4, вы можете использовать NumPy очень эффективно:

import numpy as np
data = np.fromstring(textdata, dtype='>u4')
# array([1952999795,  543781664, 1836654708, 1702065184, 1684108385])

'>u4' означает «4-байтовое целое число без знака с прямым порядком байтов».

Редактировать : Если вы используете NumPy> = 1.14, то np.fromstring устарела, и правильный способ обработать ваш текст - вызвать np.frombuffer(textdata.encode(), dtype='>u4').

0 голосов
/ 05 июля 2018

Используя numpy:

>>> import numpy as np

>>> a = np.frombuffer(b'this is my test data', dtype=np.int32)
>>> a
array([1936287860,  544434464, 1948285293,  544502629, 1635017060], dtype=int32)
>>> a.tobytes()
b'this is my test data'

Используйте '<i4' или аналогичный как dtype для переносимости между машинами.

Я предполагаю, что вы можете сохранить свои исходные данные как bytes, а не unicode, потому что вам действительно стоит постараться сделать это.

0 голосов
/ 05 июля 2018

Вы можете использовать что-то вроде следующего, которое использует битовую манипуляцию (big-endian):

def chunk2int(chunk):
    """ Converts a chunk (string) into an int, 8 bits per character """
    val = 0
    for c in chunk:
        val = (val << 8) | (ord(c) & 0xFF)
    return val

def int2chunk(val):
    """ Converts an int into a chunk, consuming 8 bits per character """
    rchunk = []
    while val:
        rchunk.append(val & 0xFF)
        val >>= 8

    return ''.join(chr(c) for c in reversed(rchunk))

textdata = "this is my test data"

chunks = [textdata[i:i + 4] for i in range(0, len(textdata), 4)]
print(chunks)

data = [chunk2int(c) for c in chunks]
print(data)

chunks = [int2chunk(d) for d in data]
print(chunks)

Производит:

['this', ' is ', 'my t', 'est ', 'data']
[1952999795, 543781664, 1836654708, 1702065184, 1684108385]
['this', ' is ', 'my t', 'est ', 'data']

Если вы используете символы с 1 <= ord(c) <= 255 во входном тексте, это будет работать. Если в вашей строке есть нулевые байты, метод int2chunk может завершиться досрочно, и в этом случае вам придется дополнить фрагменты.

Также есть модуль struct , который, возможно, стоит изучить, и где вы можете изменить порядок байтов намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...