Slice a binary number into groups of five digits

人走茶凉 提交于 2019-12-20 02:47:07

问题


Is there any neat trick to slice a binary number into groups of five digits in python?

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

Edit: I want to write a cipher/encoder in order to generate "easy to read over the phone" tokens. The standard base32 encoding has the following disadvantages:

  • Potential to generate accidental f*words
  • Uses confusing chars like chars like 'I', 'L', 'O' (may be confused with 0 and 1)
  • Easy to guess sequences ("AAAA", "AAAB", ...)

I was able to roll my own in 20 lines of python, thanks everybody. My encoder leaves off 'I', 'L', 'O' and 'U', and the resulting sequences are hard to guess.


回答1:


>>> a='00010100011011101101110100010111'
>>> [a[i:i+5] for i in range(0, len(a), 5)]
['00010', '10001', '10111', '01101', '11010', '00101', '11']



回答2:


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

or:

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

[EDIT]

The question was raised by Greg Hewgill, what to do with the two trailing bits? Here are some possibilities:

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



回答3:


Another way to group iterables, from the itertools examples:

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



回答4:


Per your comments, you actually want base 32 strings.

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



回答5:


How about using a regular expression?

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

This will break though if your input string contains newlines, that you want in the grouping.




回答6:


My question was duplicated by this one, so I would answer it here.

I got a more general and memory efficient answer for all this kinds of questions using 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

So for this question, We can do:

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


来源:https://stackoverflow.com/questions/4028313/slice-a-binary-number-into-groups-of-five-digits

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!