1

我在 python 中有一个相当大的字节数组。在最简单的情况下,字节数组只包含 0 或 1 个值(0x00、0x01),而且数组的长度始终是 8 的倍数。如何将这些“位”打包到另一个字节数组中(它不需要是可变的),以便源索引零进入第一个输出字节的 MSB 等。

例如,如果src = bytearray([1,0,0,0,1,0,0,1, 1,1,1,0,0,0,1,0, 1,1,1,1,1,1,1,1]) 期望的输出是b'\x89\xe2\xff'.

我可以使用 for 循环和位移位以及 or-ing 和连接来做到这一点,但肯定有更快/更好的内置方法来做到这一点。

在后续问题中,我还可能希望源字节数组包含集合 0-3 中的值,并将这 4 个一次打包到输出数组中。有没有办法做到这一点?

一般来说,有没有办法将列表的元素解释为真或假,并将它们一次打包 8 个到一个字节数组中?

4

2 回答 2

3
于 2018-07-17T05:00:38.250 回答
0

使用 numpy,带有测试代码和注释:

#!/usr/bin/env python3
import numpy as np


def pack_bits(a):
    # big-endian - use '<u8' if you want little-endian
    #0000000A0000000B0000000C0000000D0000000E0000000F0000000G0000000H
    b = np.copy(a.view('>u8'))
    #0000000A000000AB000000BC000000CD000000DE000000EF000000FG000000GH
    b |= b >> 7
    #0000000A000000AB00000ABC0000ABCD0000BCDE0000CDEF0000DEFG0000EFGH
    b |= b >> 14
    #0000000A000000AB00000ABC0000ABCD000ABCDE00ABCDEF0ABCDEFGABCDEFGH
    b |= b >> 28
    return np.array(b, dtype='u1')

def main():
    a = []
    for i in range(256):
        # build 8-bit lists without numpy, then convert
        a.append(np.array([int(b) for b in bin(256 + i)[2+1:]], dtype='u1'))
    a = np.array(a)
    print(a)
    b = pack_bits(a)
    print(b)

if __name__ == '__main__':
    main()

其他去交织也存在类似的代码,位由于输入之间的位数小于一个字中的字节数,我们可以避免这里的掩码(注意0ABCDEFG不与 重叠ABCDEFGH)。

于 2018-07-17T05:34:00.817 回答