1

If I have a Python list (data) and two integers (i and count), I can easily append count copies of i to data:

>>> data = [0]
>>> i, count = 1, 4
>>> data += [i] * count
>>> data
[0, 1, 1, 1, 1]

How can I do the same if data is a bytearray? Is it necessary to create a list first, e.g. data += bytearray([i] * count)?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
user200783
  • 13,722
  • 12
  • 69
  • 135
  • 1
    Did you try anything? If it didn't work, what's the code & error? I don't see any `bytearray`'s in the code provided to start with. – ivan_pozdeev Apr 10 '16 at 02:06

2 Answers2

4

If you don't mind using import i would suggest itertools.repeat.

>>> from itertools import repeat
>>> data = bytearray([0])
>>> data.extend(repeat(1, 3))
>>> data
bytearray(b'\x00\x01\x01\x01')
robyschek
  • 1,995
  • 14
  • 19
  • I would like to contest the "fast" assertion - on my machine it is more than 27 times slower than naive multiplication when testing with 6000000000 iterations: http://i.imgur.com/6utNJVc.png The gap seems to worsen with larger numbers too, though that is probably in part due to python's warmup time being taken out of the equation. – Score_Under Apr 10 '16 at 02:26
  • @Score_Under, on small N itertools is _up_ _to_ :) 40% faster on my machine `In [32]: %timeit s=bytearray(); s.extend(repeat(1, 1000000))`
    `100 loops, best of 3: 10.4 ms per loop` `In [33]: %timeit bytearray([1]*1000000)` `100 loops, best of 3: 15 ms per loop` On such huge numbers i guess the slowdown is due to swapping in array reallocation.
    – robyschek Apr 10 '16 at 22:51
  • 1
    you need to multiply the bytearray rather than the list - list multiplication is probably the least efficient way to do this, which is why I steered away from it quickly in my answer. For some reason I can't @-mention you, is this a bug? – Score_Under Apr 11 '16 at 00:00
  • @Score_Under, You are completly right; just tested `15.2ms` vs `317µs`. And my assertion about O(1) memory may be also wrong cause the growing array needs to be realloced, wich often involves malloc+memcpy+free – robyschek Apr 11 '16 at 02:15
3

Is it necessary to create a list first, e.g. data += bytearray([i] * count)?

That is indeed one way to do it. You can do the multiply operation on the byte array (as opposed to the list), which is slightly more memory-efficient and much faster for large values of count*:

>>> data = bytearray([0])
>>> i, count = 1, 4
>>> data += bytearray((i,)) * count
>>> data
bytearray(b'\x00\x01\x01\x01\x01')

* source: Works on my machine; YMMV! Tried with a count of 4000000000, which went out of memory when multiplying the list, but not when multiplying the bytearray. Smaller values of count (600000000) use more than 8 times as much memory when multiplying a list than when multiplying a bytearray.

Score_Under
  • 1,189
  • 10
  • 20