Louis.CLast
Louis.CLast

Reputation: 454

How to convert a list with multiple types to binary in Python?

I have an array with two elements: the first is type, the second is a data array I need to convert.

[['string','int32','string','int64','float32','string','string'],['any string','19','any string','198732132451654654','0.6','any string','any string']]

I know how to convert integer to binary, but in the above array with multiple types, how do I convert it to binary?

Upvotes: 2

Views: 1845

Answers (3)

martineau
martineau

Reputation: 123463

Here's a good way to do it:

data = [['string','int32','string','int64','float32','string','string'],
        ['any string','19','any string','198732132451654654','0.6',
         'any string','any string']]

type_map = {'string': str, 'int32': int, 'int64': long, 'float32': float}
results = [type_map[t](d) for t, d in zip(data[0], data[1])]
print results

Results:

['any string', 19, 'any string', 198732132451654654L, 0.6, 'any string', 'any string']

This creates the result list by looking up a conversion function in the type_map dictionary using the type string as a key for each item in the first list, and then calls it with the corresponding data item from the second list. Lists can be created with a for loop right in a list declaration by using something called a list comprehension. The zip function is used here to create pairs of values from each sublist for each iteration of the loop.

Upvotes: 2

martineau
martineau

Reputation: 123463

Although you've accepted my other answer, after noticing your comment explaining that what you really wanted was to convert the data into binary using struct.pack(), I've written another that might suit you even better (despite being longer and a little more complicated).

import struct

class TypeConv(object):
    BSA = '='  # native Byte order, standard Size, with no Alignment
    def __init__(self, conv_func, fmt_chr):
        self.__dict__.update(conv_func=conv_func, fmt_chr=fmt_chr)

    def pack(self, data):
        py_value = self.conv_func(data)
        count = str(len(py_value)) if self.conv_func is str else ''
        return struct.pack(self.BSA+count+self.fmt_chr, py_value)

type_conv = {'string': TypeConv(str, 's'),
             'int32': TypeConv(int, 'i'),
             'int64': TypeConv(long, 'q'),
             'float32': TypeConv(float, 'f'),
            }

array = [['string', 'int32', 'string', 'int64', 'float32', 'string', 'string'],
         ['any string', '19', 'any string', '198732132451654654',
          '0.6', 'any string', 'any string']]

binary_values = [type_conv[type_id].pack(data)
                     for type_id, data in zip(array[0], array[1])
                         if type_id in type_conv]  # to skip any unknown type_ids
print binary_values

Output:

['any string', '\x13\x00\x00\x00', 'any string', '\xfe\x9b<P\xd2\t\xc2\x02',
 '\x9a\x99\x19?', 'any string', 'any string']

The TypeConv.pack() method first converts the string value to its equivalent Python value py_value, then uses struct.pack() to convert that to a C binary value -- which I think is what you seek.

Upvotes: 0

mjgpy3
mjgpy3

Reputation: 8937

I am not sure if this is exactly what you want or not, but I think this is what you are looking for:

casts = { 'string': lambda x: str(x), \
    'int32': lambda x: int(x), \
    'int64': lambda x: int(x), \
    'float32': lambda x: float(x) }

types_to_cast = [['string','int32','string','int64','float32','string','string'],['any string','19','any string','198732132451654654','0.6','any string','any string']]

print [casts[types_to_cast[0][i]](types_to_cast[1][i]) for i in range(len(types_to_cast[0]))]

Upvotes: 0

Related Questions