【问题标题】:Slice a binary number into groups of five digits将二进制数分割成五位数的组
【发布时间】:2010-10-26 21:47:30
【问题描述】:

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

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

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

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

我能够用 20 行 python 编写自己的代码,谢谢大家。我的编码器去掉了“I”、“L”、“O”和“U”,结果序列很难猜。

【问题讨论】:

  • 为什么你有一个数字作为基数 2 字符串?为什么不是一个实际的整数?
  • 我需要编写编码器/密码来生成“易于通过电话阅读”令牌,我的第一个想法是某种 base32 编码,base32 中的每个数字都是 5 个二进制数字。
  • 那就这么说吧。 base64.b32encode(yourstring).

标签: python slice


【解决方案1】:
>>> a='00010100011011101101110100010111'
>>> [a[i:i+5] for i in range(0, len(a), 5)]
['00010', '10001', '10111', '01101', '11010', '00101', '11']

【讨论】:

  • +1 最喜欢这个解决方案,因为它使用基本的东西并且可读性很好。
【解决方案2】:
>>> [''.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']

【讨论】:

  • 我将首先将其填充到最大值的位长度(它是 5 的倍数,因此永远不会有任何尾随位)。
【解决方案3】:

另一种分组迭代的方法,来自itertools 示例:

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

【讨论】:

    【解决方案4】:

    根据您的 cmets,您实际上需要 32 个基数的字符串。

    >>> import base64
    >>> base64.b32encode("good stuff")
    'M5XW6ZBAON2HKZTG'
    

    【讨论】:

      【解决方案5】:

      使用正则表达式怎么样?

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

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

      【讨论】:

        【解决方案6】:

        My question被这个重复了,所以我会在这里回答。

        我使用Generators 得到了所有此类问题的更通用且内存效率更高的答案

        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']
        

        【讨论】:

          【解决方案7】:
          >>> 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']
          >>> 
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-08-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-09-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多