将字符串转换为位列表,反之亦然

Dan*_*Dan 13 python python-3.x

我需要将ASCII字符串转换为位列表,反之亦然:

str = "Hi" -> [0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1]

[0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1] -> "Hi"
Run Code Online (Sandbox Code Playgroud)

sen*_*rle 29

使用库函数有很多方法可以做到这一点.但我偏爱第三方bitarray模块.

>>> import bitarray
>>> ba = bitarray.bitarray()
Run Code Online (Sandbox Code Playgroud)

从字符串转换需要一些仪式.曾几何时,您可以使用fromstring,但现在不推荐使用该方法,因为它必须将字符串隐式编码为字节.为了避免不可避免的编码错误,最好将bytes对象传递给frombytes.从字符串开始时,这意味着您必须明确指定编码 - 无论如何这是一种很好的做法.

>>> ba.frombytes('Hi'.encode('utf-8'))
>>> ba
bitarray('0100100001101001')
Run Code Online (Sandbox Code Playgroud)

转换为列表很容易.(此外,bitstring对象已经有很多类似列表的函数.)

>>> l = ba.tolist()
>>> l
[False, True, False, False, True, False, False, False, 
 False, True, True, False, True, False, False, True]
Run Code Online (Sandbox Code Playgroud)

bitstrings可以从任何可迭代创建:

>>> bitarray.bitarray(l)
bitarray('0100100001101001')
Run Code Online (Sandbox Code Playgroud)

转换回字节或字符串也相对容易:

>>> bitarray.bitarray(l).tobytes().decode('utf-8')
'Hi'
Run Code Online (Sandbox Code Playgroud)

为了纯粹的娱乐:

>>> def s_to_bitlist(s):
...     ords = (ord(c) for c in s)
...     shifts = (7, 6, 5, 4, 3, 2, 1, 0)
...     return [(o >> shift) & 1 for o in ords for shift in shifts]
... 
>>> def bitlist_to_chars(bl):
...     bi = iter(bl)
...     bytes = zip(*(bi,) * 8)
...     shifts = (7, 6, 5, 4, 3, 2, 1, 0)
...     for byte in bytes:
...         yield chr(sum(bit << s for bit, s in zip(byte, shifts)))
... 
>>> def bitlist_to_s(bl):
...     return ''.join(bitlist_to_chars(bl))
... 
>>> s_to_bitlist('Hi')
[0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1]
>>> bitlist_to_s(s_to_bitlist('Hi'))
'Hi'
Run Code Online (Sandbox Code Playgroud)


Joh*_*Jr. 18

可能有更快的方法来执行此操作,但不使用额外的模块:

def tobits(s):
    result = []
    for c in s:
        bits = bin(ord(c))[2:]
        bits = '00000000'[len(bits):] + bits
        result.extend([int(b) for b in bits])
    return result

def frombits(bits):
    chars = []
    for b in range(len(bits) / 8):
        byte = bits[b*8:(b+1)*8]
        chars.append(chr(int(''.join([str(bit) for bit in byte]), 2)))
    return ''.join(chars)
Run Code Online (Sandbox Code Playgroud)

  • 这应该有效,而不是切割0的字符串.在[1]中:msg ="101"在[2]中:msg.zfill(8)输出[2]:'00000101' (2认同)

ch3*_*3ka 7

不知道为什么,但这里有两个只使用内置的丑陋oneliners:

s = "Hi"
l = map(int, ''.join([bin(ord(i)).lstrip('0b').rjust(8,'0') for i in s]))
s = "".join(chr(int("".join(map(str,l[i:i+8])),2)) for i in range(0,len(l),8))
Run Code Online (Sandbox Code Playgroud)

收益率:

>>> l
[0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1]
>>> s
'Hi'
Run Code Online (Sandbox Code Playgroud)

在现实世界的代码中,使用structbitarray模块.

  • 大声笑,现在我知道为什么我不应该使用"l"作为变量名...从来没有我的控制台字体的问题:D (2认同)

Rik*_*ggi 5

您可以使用内置的bytearray

>>> for i in bytearray('Hi', 'ascii'):
...     print(i)
... 
72
105

>>> bytearray([72, 105]).decode('ascii')
'Hi'
Run Code Online (Sandbox Code Playgroud)

bin()转换为二进制。