0

I want to convert back from bytes the list of tuples I had.

lst is a list of tuples (x,y), x and y are integer.

The code of converting to bytes is:

b = b''.join([(x << 16 | (y & 2 ** 16 - 1)).to_bytes(6, 'big') for x, y in lst])

Now I want to write function that get that b variable and convert him back to that list.
How can I do it?

while(b!=b''):
   Z=b[:6]
   Q=Z[4:]
   A=int.from_bytes(Q,'big')
   w=int.from_bytes(z,'big')
   w=w>>16
   lst.append((w,A))
   b=b[6:]

for example for the list ([(1, 1), (2, 2)], [(1, 1), (2, 1)], [(2, 1)], [(1, 2), (2, 1)]) convert to bytes.

The code that I wrote that convert bytes back to the list, I get the list:

([(1, 1), (1, 2)], [(1, 1), (1, 1)], [(1, 1)], [(1, 2), (1, 1)])

  • You can probably split the bytes back into integers based on 16 digits or so, then convert to integers. – Larry the Llama Nov 10 '21 at 09:10
  • You'll get a TypeError exception with that code. Perhaps you could explain what your ultimate objective is –  Nov 10 '21 at 09:16
  • Also... Let's assume that x is actually an integer (even though you've said it's a string) so we'll ignore that. Now let's say that y == 0. Apply that to the y-based formula and you'll get a result of zero. However, if y == 65536, the result will also be zero. Therefore, you can never be certain what the original value was when you try to 'decode' the byte list –  Nov 10 '21 at 09:36
  • @lirongr1996 Perhaps you missed my previous comment. This cannot be done **UNLESS** you know that the y-values are 0 <= y < 65536. Other values will produce ambiguous results. –  Nov 10 '21 at 10:32

2 Answers2

1

You can't do what you want for arbitrary integer values because there's a loss of information with the way they're being converting to a stream of bytes. However, for unsigned values of x up to 4,294,967,295 and of y up to 65535 the following would work:

def grouper(n, iterable):
    "s -> (s0, s1, ...sn-1), (sn, sn+1, ...s2n-1), (s2n, s2n+1, ...s3n-1), ..."
    return zip(*[iter(iterable)]*n)

lst = [(0,65_535), (2,3), (4,5), (4_294_967_295, 42)]
bytes_ = b''.join([(x << 16 | (y & 2 ** 16 - 1)).to_bytes(6, 'big') for x, y in lst])
ints = (int.from_bytes(group, 'big') for group in grouper(6, bytes_))
tuples = [((v & 0xffffffff0000) >> 16, v & 0x00000000ffff) for v in ints]
print(tuples)  # -> [(0, 65535), (2, 3), (4, 5), (4294967295, 42)]
martineau
  • 119,623
  • 25
  • 170
  • 301
0
# Encode
x_encoded = bytes([t[0] for t in lst])
y_encoded = bytes([t[1] for t in lst])
# Decode
x_decoded = [v for v in x_encoded]
y_decoded = [v for v in y_encoded]

result = list(zip(x_decoded, y_decoded))

Simply accessing the encoded data using indexes converts them back to integers.

References: Convert bytes to int?

Larry the Llama
  • 958
  • 3
  • 13