Повышение эффективности повторяющегося кода в Python - PullRequest
0 голосов
/ 31 мая 2018

Мне нужно сделать следующую операцию в Python:

У меня есть список кортежей

data = [("John", 14, 12132.213, "Y", 34), ("Andrew", 23, 2121.21, "N", 66)]

У меня есть список полей:

fields = ["name", "age", "vol", "status", "limit"]

Каждый кортеж данных предназначен для каждого из полей в следующем порядке.

У меня есть dict

desc = { "name" : "string", "age" : "int", "vol" : "double", "status" : "byte", "limit" : "int" }

Мне нужно создать сообщение для отправки в следующем формате:

[{"column": "name", "value": {"String": "John"}}, {"column": "age", "value": {"Int": 14}}, {"column": "vol", "value": {"Double": 12132.213}}, {"column": "status", "value": {"Byte": 89}}, {"column": "limit", "value": {"Int": 34}},
{"column": "name", "value": {"String": "Andrew"}}, {"column": "age", "value": {"Int": 23}}, {"column": "vol", "value": {"Double":2121.21}}, {"column": "status", "value": {"Byte": 78}}, {"column": "limit", "value": {"Int": 66}}]

У меня есть две функции, которые генерируют это:

def get_value(data_type, res):
    if data_type == 'string':
       return {'String' : res.strip()}
    elif data_type == 'byte' :
       return {'Byte' : ord(res[0])} 
    elif data_type == 'int':
       return {'Int' : int(res)}
    elif data_type == 'double':
       return {'Double' : float(res)}

def generate_message(data, fields, desc):
    result = []
    for row in data:
       for field, res in zip(fields, row):
           data_type = desc[field]
           val = {'column' : field, 
                  'value'  : get_value(data_type, res)}
           result.append(val)
    return result

Однако данные действительно велики с огромным количеством кортежей (~ 200 000).Генерация вышеуказанного формата сообщения для каждого из них занимает много времени.Есть ли эффективный способ сделать это.

PS Нужно такое сообщение, так как я отправляю его в очередь, а потребителем является клиент C ++, которому нужна информация о типе.

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Опираясь на ответ Айдова и ускоряя немного больше:

dt_action = {
  'string': (lambda res: {'String': res.strip()}),
  'byte': (lambda res: ord(res[0])),
  'int': (lambda res: int(res)),
  'double': (lambda res: float(res)),
}

def generate_message_faster(data, fields, desc):
  return [
    {'column': field, 'value': dt_action[desc[field]](res)}
    for row in data for field, res in zip(fields, row)
  ]

Время:

  • оригинал 6.44 µs per loop
  • с dt_action: 5.54 µs per loop
  • с dt_action и списком: 4.92 µs per loop
0 голосов
/ 31 мая 2018

Список понимания должен быть быстрее.Они также читабельны и лаконичны.

In [94]: def generate_message_faster(data, fields, desc):
    ...:     return [
    ...:        {'column': field, 'value': get_value(desc[field], res)} 
    ...:        for row in data for field, res in zip(fields, row)
    ...:     ]
    ...:

In [95]: generate_message_fast(data, fields, desc)
Out[95]:
[{'column': 'name', 'value': {'String': 'John'}},
 {'column': 'age', 'value': {'Int': 14}},
 {'column': 'vol', 'value': {'Double': 12132.213}},
 {'column': 'status', 'value': {'Byte': 89}},
 {'column': 'limit', 'value': {'Int': 34}},
 {'column': 'name', 'value': {'String': 'Andrew'}},
 {'column': 'age', 'value': {'Int': 23}},
 {'column': 'vol', 'value': {'Double': 2121.21}},
 {'column': 'status', 'value': {'Byte': 78}},
 {'column': 'limit', 'value': {'Int': 66}}]

In [96]: %timeit(generate_message(data, fields, desc))
100000 loops, best of 3: 7.84 µs per loop

In [97]: %timeit(generate_message_faster(data, fields, desc))
The slowest run took 4.24 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 5.9 µs per loop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...