Chunking bytes (not strings) in Python 2 and 3

前端 未结 2 869
旧时难觅i
旧时难觅i 2021-02-14 06:41

This is turning out to be trickier than I expected. I have a byte string:

data = b\'abcdefghijklmnopqrstuvwxyz\'

I want to read this data in c

相关标签:
2条回答
  • 2021-02-14 07:09

    Funcy (a library offering various useful utilities, supporting both Python 2 and 3) offers a chunks function that does exactly this:

    >>> import funcy
    >>> data = b'abcdefghijklmnopqrstuvwxyz'
    >>> list(funcy.chunks(6, data))
    [b'abcdef', b'ghijkl', b'mnopqr', b'stuvwx', b'yz']   # Python 3
    ['abcdef', 'ghijkl', 'mnopqr', 'stuvwx', 'yz']        # Python 2.7
    

    Alternatively, you could include a simple implementation of this in your program (compatible with both Python 2.7 and 3):

    def chunked(size, source):
        for i in range(0, len(source), size):
            yield source[i:i+size]
    

    It behaves the same (at least for your data; Funcy's chunks also works with iterators, this doesn't):

    >>> list(chunked(6, data))
    [b'abcdef', b'ghijkl', b'mnopqr', b'stuvwx', b'yz']   # Python 3
    ['abcdef', 'ghijkl', 'mnopqr', 'stuvwx', 'yz']        # Python 2.7
    
    0 讨论(0)
  • 2021-02-14 07:14

    Using bytes with bytearray would work for both if your string length was divisible by n or you pass a non empty string as the fillvalue:

    def grouper(iterable, n, fillvalue=None):
        "Collect data into fixed-length chunks or blocks"
        # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
        args = [iter(iterable)] * n
        return ((bytes(bytearray(x))) for x in zip_longest(fillvalue=fillvalue, *args))
    

    py3:

    In [20]: import sys
    
    In [21]: sys.version
    Out[21]: '3.4.3 (default, Oct 14 2015, 20:28:29) \n[GCC 4.8.4]'
    
    In [22]: print(list(grouper(data,2)))
    [b'ab', b'cd', b'ef', b'gh', b'ij', b'kl', b'mn', b'op', b'qr', b'st', b'uv', b'wx', b'yz']
    

    Py2:

    In [6]: import sys
    
    In [7]: sys.version
    Out[7]: '2.7.6 (default, Jun 22 2015, 17:58:13) \n[GCC 4.8.2]'
    
    In [8]: print(list(grouper(data,2)))
    ['ab', 'cd', 'ef', 'gh', 'ij', 'kl', 'mn', 'op', 'qr', 'st', 'uv', 'wx', 'yz']
    

    If you passed an empty string you could filter them out:

    def grouper(iterable, n, fillvalue=None):
        "Collect data into fixed-length chunks or blocks"
        # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
        args = [iter(iterable)] * n
        return ((bytes(bytearray(filter(None, x)))) for x in zip_longest(fillvalue=fillvalue, *args))
    

    Which will work for any length string.

    In [29]: print(list(grouper(data,4)))
    [b'abcd', b'efgh', b'ijkl', b'mnop', b'qrst', b'uvwx', b'yz']
    
    In [30]: print(list(grouper(data,3)))
    [b'abc', b'def', b'ghi', b'jkl', b'mno', b'pqr', b'stu', b'vwx', b'yz']
    
    0 讨论(0)
提交回复
热议问题