我有一个长的一维整数1和0的列表,代表8位二进制字节。从中创建一个包含整数字节的新列表的方法是什么。在
我熟悉C,但对Python还不熟悉,所以我用C编写代码:一个经过每一位循环的复杂结构。然而,我知道Python over C的全部意义在于,这些事情通常可以紧凑而优雅地完成,我应该学习如何做到这一点。也许用列表理解法?在
这是可行的,但建议采用更“Python式”的方法,我们将不胜感激:
#!/usr/bin/env python2
bits = [1,0,0,1,0,1,0,1,0,1,1,0,1,0,1,1,1,1,1,0,0,1,1,1]
bytes = []
byt = ""
for bit in bits:
byt += str(bit)
if len(byt) == 8:
bytes += [int(byt, 2)]
byt = ""
print bytes
$ bits-to-bytes.py
[149, 107, 231]
您可以将列表分成8个元素的块,并将子元素映射到str:
您可以将其分为两部分:映射和连接一次:
^{pr2}$或者使用iter并借用itertools中的grouperrecipe:
iter(map(str, bits))
将位的内容映射到str并创建一个iterator,zip(*iter([it] * 8))
将元素分成8个子元素的组。每个
zip(*iter..
使用迭代器中的八个子元素,因此我们总是得到顺序组,这与第一个代码中的切片逻辑相同,我们只是避免了切片的需要。在正如Sven所说,对于不能被
n
整除的列表,使用zip将丢失与原始代码类似的数据,您可以调整我链接的grouper配方来处理这些情况:fillvalue=""
意味着我们用空字符串填充奇数长度组,这样我们仍然可以调用int("".join(sli), 2)
并获得正确的输出,如上面所示,在获取3 * 8
块之后,我们只剩下1,0
。在在您自己的代码中,
bytes += [int(byt, 2)]
可以简单地变成bytes.append(int(byt, 2))
Padraic的解决方案很好;还有另一种方法:
由于从数字列表开始,您可能希望避免字符串操作。这里有两种方法:
将原始列表分为8位块并计算每个字节的十进制值(假设位的数量是8的倍数);感谢Padraic Cunningham用8个子元素的组来划分序列的好方法
使用位运算符(可能效率更高);如果位数不是8的倍数,则代码的工作方式就好像比特序列在左边填充了0(左边的填充通常比右边的填充更有意义,因为它保留了原始二进制数字序列的数值
相关问题 更多 >
编程相关推荐