使用Python将二进制字符串转换为整数列表

5 投票
5 回答
10847 浏览
提问于 2025-04-15 14:07

我刚开始学Python。以下是我想做的事情:

  1. 把一个很长的二进制字符串切分成每组三位的块。
  2. 把每个“块”存储到一个叫做row的列表里。
  3. 把每个二进制块转换成一个数字(范围是0到7)。
  4. 把转换后的数字列表存储到一个新的列表叫做numbers里。

这是我目前的进展:

def traverse(R):
        x = 0
        while x < (len(R) - 3):
            row = R[x] + R[x+1] + R[x+2]
            ???

谢谢你的帮助!我非常感激。

5 个回答

1

这样做不是更简单吗:

(我想要一个包含整数29的变量的高3位的数组)

先格式化你的变量和数组

a = ''

b = []

我从这个论坛的一个很好的例子中学来的,它把整数29格式化成5位二进制数,也就是从第0位到第4位,然后把这些位的字符串放到字符串变量"a"里。[编辑] 需要把格式从0:5b改成0:05b,这样当整数小于7时就能补零。

a = '{0:05b}'.format(29)

看看你的字符串变量

a

'11101'

把你的字符串分割成一个数组

b[0:3] = a[0:3]

这正是我想要的。

b

['1', '1', '1']

7

我假设你所说的“二进制字符串”其实是指一个普通的字符串(也就是文本),里面的内容全是‘0’或‘1’。

关于第1点和第2点,

row = [thestring[i:i+3] for i in xrange(0, len(thestring), 3)]

当然,如果len(thestring)不是3的整倍数,最后的部分长度只会是1或2个字符,这是不可避免的;-).

对于第3点和第4点,我建议你建立一个辅助的临时字典来存储数据:

aux = {}
for x in range(8):
  s = format(x, 'b')
  aux[s] = x
  aux[('00'+s)[-3:]] = x

这样第3点和第4点就变成了:

numbers = [aux[x] for x in row]

这个字典查找应该比每次动态转换每个条目要快得多。

编辑:有人建议我解释一下为什么我对每个x的值在aux中做了两个条目。原因是s的长度可以是1到3个字符,对于短的长度我确实想要两个条目——一个是s本身(因为我提到过row中的最后一项可能短于3个字符...),另一个是用0填充到3个字符的长度。

子表达式('00'+s)[-3:]的作用是计算“用‘0’填充到3个字符长度的”,通过取字符串中最后3个字符(这就是[-3:]切片的部分),而这个字符串是通过在s前面加上‘00’得到的(这就是'00'+s的部分)。如果s已经是3个字符长,那么整个子表达式就等于s,所以对aux的这个条目的赋值是多余的,但也没什么坏处,因此我觉得不检查更简单(加上if len(s)<3:也是可以的,这只是个人喜好;-)。

还有其他方法(比如在需要时再次格式化x),但这并不是代码的关键部分(毕竟它只执行8次来构建辅助的“查找表”;-),所以我没有太关注这个。

...我也没有进行单元测试,所以在某个不明显的边缘情况下有个bug。你能发现吗...?

假设row的最后一个条目是'01':在我上面的代码构建aux后,那个键将不会出现在aux中(1001会存在,但这并不能让人感到安慰;-)。在上面的代码中,我使用了原始的s'1',以及填充到三位的版本'001',但中间的长度为2的填充版本,哎呀,被忽略了;-)。

所以,这里有一个正确的方法来做这件事...:

aux = {}
for x in range(8):
  s = format(x, 'b')
  aux[s] = x
  while len(s) < 3:
    s = '0' + s
    aux[s] = x

...毫无疑问,这个方法更简单、更明显,但更重要的是,它是正确的;-).

11

像这样应该可以实现:

s = "110101001"
numbers = [int(s[i:i+3], 2) for i in range(0, len(s), 3)]
print numbers

输出结果是:

[6, 5, 1]

一步一步来分析,首先:

>>> range(0, len(s), 3)
[0, 3, 6]

range() 函数会生成一个从 0 开始,到小于最大值 len(s) 的整数列表,步长为 3。

>>> [s[i:i+3] for i in range(0, len(s), 3)]
["110", "101", "001"]

这是一个列表推导式,它会对上面范围内的每个 i 计算 s[i:i+3]。这里的 s[i:i+3] 是一个切片,用来选择一个子字符串。最后:

>>> [int(s[i:i+3], 2) for i in range(0, len(s), 3)]
[6, 5, 1]

int(..., 2) 函数将二进制(基数为 2,第二个参数)转换为整数。

请注意,上面的代码可能无法正确处理一些错误情况,比如输入字符串的长度不是 3 的倍数。

撰写回答