3

有没有什么巧妙的技巧可以在 python 中将二进制数分成五位数的组?

'00010100011011101101110100010111' => ['00010', '00110', '10111', ... ]

编辑:我想编写一个密码/编码器以生成“易于通过电话阅读”令牌。标准 base32 编码有以下缺点:

  • 可能会产生意外的 f*words
  • 使用混淆字符,例如 'I'、'L'、'O'(可能与 0 和 1 混淆)
  • 易于猜测的序列(“AAAA”、“AAAB”、...)

我能够在 20 行 python 中自行开发,谢谢大家。我的编码器去掉了“I”、“L”、“O”和“U”,结果序列很难猜到。

4

7 回答 7

6
>>> a='00010100011011101101110100010111'
>>> [a[i:i+5] for i in range(0, len(a), 5)]
['00010', '10001', '10111', '01101', '11010', '00101', '11']
于 2010-10-26T21:52:27.357 回答
6
>>> [''.join(each) for each in zip(*[iter(s)]*5)]
['00010', '10001', '10111', '01101', '11010', '00101']

或者:

>>> map(''.join, zip(*[iter(s)]*5))
['00010', '10001', '10111', '01101', '11010', '00101']

[编辑]

Greg Hewgill 提出了这个问题,如何处理两个尾随位?以下是一些可能性:

>>> from itertools import izip_longest
>>>
>>> map(''.join, izip_longest(*[iter(s)]*5, fillvalue=''))
['00010', '10001', '10111', '01101', '11010', '00101', '11']
>>>
>>> map(''.join, izip_longest(*[iter(s)]*5, fillvalue=' '))
['00010', '10001', '10111', '01101', '11010', '00101', '11   ']
>>>
>>> map(''.join, izip_longest(*[iter(s)]*5, fillvalue='0'))
['00010', '10001', '10111', '01101', '11010', '00101', '11000']
于 2010-10-26T22:02:59.493 回答
1

另一种对可迭代对象进行分组的方法,来自itertools示例:

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)
于 2010-10-26T21:52:56.537 回答
1

根据您的评论,您实际上需要 32 个基本字符串。

>>> import base64
>>> base64.b32encode("good stuff")
'M5XW6ZBAON2HKZTG'
于 2010-10-26T22:54:28.557 回答
1

使用正则表达式怎么样?

>>> import re
>>> re.findall('.{1,5}', '00010100011011101101110100010111')
['00010', '10001', '10111', '01101', '11010', '00101', '11']

如果您的输入字符串包含您想要在分组中的换行符,这将中断。

于 2010-10-26T23:17:47.507 回答
1

我的问题被这个重复了,所以我会在这里回答。

对于使用生成器的所有此类问题,我得到了更通用且内存效率更高的答案

from itertools import islice
def slice_generator(an_iter, num):
    an_iter = iter(an_iter)
    while True:
        result = tuple(islice(an_iter, num))
        if not result:
           return
        yield result

所以对于这个问题,我们可以这样做:

>>> l = '00010100011011101101110100010111'
>>> [''.join(x) for x in slice_generator(l,5)]
['00010', '10001', '10111', '01101', '11010', '00101', '11']
于 2015-04-12T16:41:56.100 回答
0
>>> l = '00010100011011101101110100010111'
>>> def splitSize(s, size):
...     return [''.join(x) for x in zip(*[list(s[t::size]) for t in range(size)])]
...  
>>> splitSize(l, 5)
['00010', '10001', '10111', '01101', '11010', '00101']
>>> 
于 2010-10-26T21:52:12.783 回答