1

Let's suppose i have 2 bigs arrays (i have put smaller arrays in this example):

a1=bytes([10,20,30,40,50,60,70,80])
a2=bytes([11,21,31,41,51,61,71,81])

What i want to do is to merge this 2 arrays this way:

[10,20 , 11,21 , 30,40 , 31,41 , ...

What i want is to take 2 bytes from first array, then 2 from second array, etc.

Here is what i done. It works but i think there is a best way to do this, without having to create intermediates arrays:

a3 = bytearray()
for i in range(0, len(a1), 2):
    a3.append(a1[i])
    a3.append(a1[i+1])
    a3.append(b1[i])
    a3.append(b1[i+1])

output_array=bytes(a3)  # Very important: i need bytes() object at the end
martineau
  • 119,623
  • 25
  • 170
  • 301
Bob5421
  • 7,757
  • 14
  • 81
  • 175

4 Answers4

2

You can do it with slice assignment:

a1 = bytes([10,20,30,40,50,60,70,80])
a2 = bytes([11,21,31,41,51,61,71,81])

n = len(a1)

a3 = bytearray(2*n)
a3[0::4] = a1[0::2]
a3[1::4] = a1[1::2]
a3[2::4] = a2[0::2]
a3[3::4] = a2[1::2]
a3 = bytes(a3)

Output:

>>> a3
b'\n\x14\x0b\x15\x1e(\x1f)2<3=FPGQ'
>>> list(a3)
[10, 20, 11, 21, 30, 40, 31, 41, 50, 60, 51, 61, 70, 80, 71, 81]

Edit: Here is a method without intermediate copies

def gen(a1, a2):
    i1 = iter(a1)
    i2 = iter(a2)
    while True:
        for it in i1, i1, i2, i2:
            try:
                yield next(it)
            except StopIteration:
                return

a3 = bytes(gen(a1, a2))
wim
  • 338,267
  • 99
  • 616
  • 750
  • 1
    do you think i can do less copies ? In the last line, does it make a copy ? – Bob5421 Aug 26 '17 at 19:04
  • Yes the last line makes a copy. I will try to think of a way to do it without that last copy.... – wim Aug 26 '17 at 19:08
  • Turns out your first solution (with the slices) is way faster than the second one – jadsq Aug 26 '17 at 20:52
  • Yeah, I'm not surprised. It uses heavily optimized parts of CPython. But speed is not the only possible reason to try and avoid copies (there can be also memory limitations warranting it). – wim Aug 26 '17 at 21:11
0

Chunk taken from here: How do you split a list into evenly sized chunks?
Merge taken from here: How do I merge two lists into a single list?

Combined into this:

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

a1 = [10,20,30,40,50,60,70,80]
b1 = [11,21,31,41,51,61,71,81]
combined = [j for i in zip(chunks(a1, 2),chunks(b1, 2)) for j in i]
out = bytes(bytearray([x for pair in combined for x in pair]))
==> b'\n\x14\x0b\x15\x1e(\x1f)2<3=FPGQ'
Dekel
  • 60,707
  • 10
  • 101
  • 129
0

This is another option:

a1=bytes([10,20,30,40,50,60,70,80])
a2=bytes([11,21,31,41,51,61,71,81])

merged = bytes((a1 if (i&3)<2 else a2)[i-(i&2)-2*(i>>2)]
               for i in range(2*len(a1)))
6502
  • 112,025
  • 15
  • 165
  • 265
0

using slice assignments on the bytes directly

a1 = bytes([10,20,30,40,50,60,70,80])
a2 = bytes([11,21,31,41,51,61,71,81])
a3 = bytes()

for i in range(int(len(a1)/2)):
    a3 += a1[i*2:i*2+2] + a2[i*2:i*2+2]
# a3 = b'\n\x14\x0b\x15\x1e(\x1f)2<3=FPGQ'
Skycc
  • 3,496
  • 1
  • 12
  • 18