Конвертировать список кортежей в словарь списков
Коллеги, есть вопрос по оптимизации. Дан список кортежей, например:
a = [(1,5,6), (7,8,9), (10,12,4)]
Сразу оговорюсь, что в реале кортежей миллионы и в каждом кортеже семь элементов, а данный пример, это только пример, для простоты восприятия.
Надо преобразовать этот список кортежей в словарь списков, таким образом чтобы все нулевые элементы кортежей стали одним списком, первые элементы - следующим списком, третьи - следующим... Ключи будут заданы вручную. Вот так:
a_d = {'key1':[1,7,10], 'key2':[5,8,12], 'key3':[6,9,4]}
Я знаю как решить эту задачу с помощью Pandas. Как-то так:
import pandas as pd
a = [(1,5,6), (7,8,9), (10,12,4)]
a_d = {key: list(val) for key, val in dict(pd.DataFrame(a, columns=['key1', 'key2', 'key3'])).items()}
Вопросов два:
- Есть ли способ решить эту задачу с помощью базового Питона и стандартных библиотек без перебора всех элементов. Может есть какой-то стандартный метод/функция, который я упускаю.
- Будет ли этот способ быстрее чем описанный выше способ через
Pandas?
Спасибо.
Ответы (2 шт):
keys=['key1', 'key2', 'key3']
a = [(1,5,6), (7,8,9), (10,12,4)]
dct = dict(zip(keys, map(list, zip(*a ))))
print (dct)
Результат:
{'key1': [1, 7, 10], 'key2': [5, 8, 12], 'key3': [6, 9, 4]}
Ответ про "быстрее" легко получить самостоятельно замерив время выполнения кода. Но советую для этого брать массив побольше, на трех или 9 элементов вы разницы можете и не получить, не знаю, не пробовал.
P.S. Кстати, обратите внимание, что в исходном списки у вас кортежи, а в результате вы хотите получить значения-списки. Это лишнее преобразование. Если вас устроят значения-кортежи, то оператор еще более сократиться до:
dct_tuples = dict(zip(keys, zip(*a )))
P.P.S. Благодаря замечания уважаемого Stanislav Volodarskiy в комментариях коды еще более сокращены. Думаю и по времени выполнения тоже.
collections.namedtuple
В ряде случаев такой тип данных удобнее и эффективнее:
from collections import namedtuple
from rich import print, inspect
a = [(1,5,6), (7,8,9), (10,12,4)]
AinNamedTuple = namedtuple(
typename='AinNamedTuple',
field_names=('key1', 'key2', 'key3')
)
a_d = AinNamedTuple._make(zip(*a))
inspect(a_d)
# пример получения значений по ключу
print(f'Пример получения значений по ключу "key1": {a_d.key1}')
output:
╭───────────────── <class '__main__.AinNamedTuple'> ──────────────────╮
│ AinNamedTuple(key1, key2, key3) │
│ │
│ ╭─────────────────────────────────────────────────────────────────╮ │
│ │ AinNamedTuple(key1=(1, 7, 10), key2=(5, 8, 12), key3=(6, 9, 4)) │ │
│ ╰─────────────────────────────────────────────────────────────────╯ │
│ │
│ key1 = (1, 7, 10) │
│ key2 = (5, 8, 12) │
│ key3 = (6, 9, 4) │
╰─────────────────────────────────────────────────────────────────────╯
Пример получения значений по ключу "key1": (1, 7, 10)