Конвертировать список кортежей в словарь списков

Рейтинг: 1Ответов: 2Опубликовано: 08.04.2023

Коллеги, есть вопрос по оптимизации. Дан список кортежей, например:

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()}

Вопросов два:

  1. Есть ли способ решить эту задачу с помощью базового Питона и стандартных библиотек без перебора всех элементов. Может есть какой-то стандартный метод/функция, который я упускаю.
  2. Будет ли этот способ быстрее чем описанный выше способ через Pandas?

Спасибо.

Ответы

▲ 4Принят
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 в комментариях коды еще более сокращены. Думаю и по времени выполнения тоже.

▲ 0

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)