首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将字节列表拆分为一组数据集。

将字节列表拆分为一组数据集。
EN

Stack Overflow用户
提问于 2015-05-11 16:26:43
回答 3查看 161关注 0票数 0

我有一些字节数据(比如图像):

00 19 01 21 09 0f 01 15 .. FF

我解析它并将其存储为一个字节列表:

[b'\x00', b'\x19', b'\x01', b'\x21', b'\x09', b'\x0f', b'\x01', b'\x15', ...]

这些是RGBA值(小endian,2个字节),我需要将其解析为dict格式,如下所示:

[{'red':0x0019, 'green':0x2101, 'blue':0x0f09, 'alpha':0x1501}, {'red':...},...]

注意:一旦我们到达0xff__,图像数据就会终止。值可以以十六进制或十进制形式存储,只要它是一致的,就不重要了。

我的尝试

代码语言:javascript
运行
复制
# our dict keys
keys = ['red', 'green', 'blue', 'alpha']

# first, grab all bytes until we hit 0xff
img = list(takewhile(lambda x: x != b'\xFF', bitstream))

# traverse img 2 bytes at a time and join them
rgba = []
for i,j in zip(img[0::2],img[1::2]):
  rgba.append(b''.join([j,i]) # j first since byteorder is 'little'

到目前为止,它将输出[0x0019, 0x2101, 0x0f09, ...]

现在,我被困在如何创建一个字典列表“吡咯烷酮”。我可以一次从列表中使用for循环和pop 4项,但这并没有真正利用Python的特性。有什么建议吗?

注:这只是一个例子,我的钥匙可以是任何东西(与图像无关)。还可以忽略len(img) % len(keys) != 0的任何问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-05-11 17:08:15

首先,使用StringIO从比特流创建一个类似文件的对象,以便于一次捕获一个8字节的块。然后,使用struct.unpack将每个8字节块转换为由4个整数组成的元组,然后用键元组进行压缩,创建一个可以直接传递给dict的列表。所有这些都封装在一个列表理解中,以便在一次传递中创建rgba

(我还使用functools.partialitertools.imap来提高可读性。)

代码语言:javascript
运行
复制
import StringIO
import re
from itertools import imap
from functools import partial

keys = ("red", "green", "blue", "alpha")
# Create an object we can read from
str_iter = StringIO.StringIO(re.sub("\xff.*", "", bitstream))
# A callable which reads 8 bytes at a time from str_iter
read_8_bytes = partial(str_iter.read, 8)
# Convert an 8-byte string into a tuple of 4 integer values
unpack_rgba = partial(struct.unpack, "<HHHH")
# An iterable of 8-byte strings
chunk_iter = iter(read_8_bytes, '')
# Map unpack_rgba over the iterator to get an iterator of 4-tuples,
# then zip each 4-tuple with the key tuple to create the desired dict
rgba = [dict(zip(keys, rgba_values))
         for rgba_values in imap(unpack_rgba, chunk_iter)]

(如果您使用类似的方法获取二进制数据

代码语言:javascript
运行
复制
with open('somefile', 'rb') as fh:
    bitstream = fh.read()

然后,您可以使用文件迭代器代替str_iter,这样您只能根据需要从文件中读取字节,而不是一次性读取所有字节。)

票数 3
EN

Stack Overflow用户

发布于 2015-05-11 17:00:10

也许不是

代码语言:javascript
运行
复制
rgba = []
for i,j in zip(img[0::2],img[1::2]):
  rgba.append(b''.join([j,i]) # j first since byteorder is 'little'

你可以把它简化成

代码语言:javascript
运行
复制
rgba = [b''.join([j,i]) for i,j in zip(img[0::2], img[1::2])]

现在,您需要对您的列表进行分组,这样您就可以从this link那里借用一个菜谱,然后得到:

代码语言:javascript
运行
复制
dict_list = [dict(zip(keys, chunk)) for chunk in chunks(rgba, 4)]

例如:

代码语言:javascript
运行
复制
>>> keys = ['red', 'green', 'blue', 'alpha']
>>> test  = [b'\x0019', b'\x2101', b'\x0f09', b'\x1501']
>>> dict(zip(keys, test))
{'blue': '\x0f09', 'alpha': '\x1501', 'green': '!01', 'red': '\x0019'}
票数 1
EN

Stack Overflow用户

发布于 2015-05-11 17:46:03

在不太花哨的情况下,你可以像这样高效地做这件事:

代码语言:javascript
运行
复制
try:
    from itertools import izip
except ImportError:  # Python 3
    izip = zip

def grouper(n, iterable):
    "s -> (s0,s1,...sn-1), (sn,sn+1,...s2n-1), (s2n,s2n+1,...s3n-1), ..."
    return izip(*[iter(iterable)]*n)

img  = [b'\x00', b'\x19', b'\x01', b'\x21', b'\x09', b'\x0f', b'\x01', b'\x15',
        b'\x01', b'\x1a', b'\x02', b'\x22', b'\x0a', b'\x10', b'\x02', b'\x16',
        b'\xff']

keys = ['red', 'green', 'blue', 'alpha']
list_of_dicts = [dict(izip(keys, group))
                    for group in grouper(4, (j+i for i,j in grouper(2, img)))]

for value in list_of_dicts:
    print(value)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30172874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档