Как объединить два списка в словарь без использования вложенных циклов
У меня есть два списка:
a = [0, 0, 0, 1, 1, 1, 1, 1, .... 99999]
b = [24, 53, 88, 32, 45, 24, 88, 53, ...... 1]
Я хочу объединить эти два списка в словарь вроде:
{
0: [24, 53, 88],
1: [32, 45, 24, 88, 53],
......
99999: [1]
}
В решении может использоваться цикл for
, который выглядит не очень хорошо и элегантно, например:
d = {}
unique_a = list(set(list_a))
for i in range(len(list_a)):
if list_a[i] in d.keys:
d[list_a[i]].append(list_b[i])
else:
d[list_a] = [list_b[i]]
Хотя это действительно работает, оно неэффективно и занимает слишком много времени, когда список чрезвычайно велик. Я хочу узнать более элегантные способы построения такого словаря?
Спасибо заранее!
Ответы
Ответ 1
Вы можете использовать defaultdict:
from collections import defaultdict
d = defaultdict(list)
list_a = [0, 0, 0, 1, 1, 1, 1, 1, 9999]
list_b = [24, 53, 88, 32, 45, 24, 88, 53, 1]
for a, b in zip(list_a, list_b):
d[a].append(b)
print(dict(d))
Вывод:
{0: [24, 53, 88], 1: [32, 45, 24, 88, 53], 9999: [1]}
Ответ 2
Альтернативный itertools.groupby()
решение:
import itertools
a = [0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3]
b = [24, 53, 88, 32, 45, 24, 88, 53, 11, 22, 33, 44, 55, 66, 77]
result = { k: [i[1] for i in g]
for k,g in itertools.groupby(sorted(zip(a, b)), key=lambda x:x[0]) }
print(result)
Выход:
{0: [24, 53, 88], 1: [24, 32, 45, 53, 88], 2: [11, 22, 33, 44, 55, 66], 3: [77]}
Ответ 3
Нет фантазийных структур, просто простого словаря.
d = {}
for x, y in zip(a, b):
d.setdefault(x, []).append(y)
Ответ 4
Вы можете сделать это с пониманием dict:
list_a = [0, 0, 0, 1, 1, 1, 1, 1]
list_b = [24, 53, 88, 32, 45, 24, 88, 53]
my_dict = {key: [] for key in set(a)} # my_dict = {0: [], 1: []}
for a, b in zip(list_a, list_b):
my_dict[a].append(b)
# {0: [24, 53, 88], 1: [32, 45, 24, 88, 53]}
Как ни странно, вы не можете сделать эту работу с помощью dict.fromkeys(set(list_a), [])
, так как это установит значение всех ключей, равных одному и тому же пустым массивам:
my_dict = dict.fromkeys(set(list_a), []) # my_dict = {0: [], 1: []}
my_dict[0].append(1) # my_dict = {0: [1], 1: [1]}
Ответ 5
A pandas
решение:
Настройка:
import pandas as pd
a = [0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 4]
b = pd.np.random.randint(0, 100, len(a)).tolist()
>>> b
Out[]: [28, 68, 71, 25, 25, 79, 30, 50, 17, 1, 35, 23, 52, 87, 21]
df = pd.DataFrame(columns=['Group', 'Value'], data=list(zip(a, b))) # Create a dataframe
>>> df
Out[]:
Group Value
0 0 28
1 0 68
2 0 71
3 1 25
4 1 25
5 1 79
6 1 30
7 1 50
8 2 17
9 2 1
10 2 35
11 3 23
12 4 52
13 4 87
14 4 21
Решение:
>>> df.groupby('Group').Value.apply(list).to_dict()
Out[]:
{0: [28, 68, 71],
1: [25, 25, 79, 30, 50],
2: [17, 1, 35],
3: [23],
4: [52, 87, 21]}
Пошаговое руководство:
- создайте
pd.DataFrame
из входных списков, a
называется Group
и b
называется Value
-
df.groupby('Group')
создает группы на основе a
-
.Value.apply(list)
получает значения для каждой группы и передает ее в list
-
.to_dict()
преобразует полученный DataFrame
в dict
Сроки:
Чтобы получить представление о таймингах для тестового набора из 1000 000 значений в 100 000 групп:
a = sorted(np.random.randint(0, 100000, 1000000).tolist())
b = pd.np.random.randint(0, 100, len(a)).tolist()
df = pd.DataFrame(columns=['Group', 'Value'], data=list(zip(a, b)))
>>> df.shape
Out[]: (1000000, 2)
%timeit df.groupby('Group').Value.apply(list).to_dict()
4.13 s ± 9.29 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Но, честно говоря, он, вероятно, менее эффективен, чем itertools.groupby
, предложенный @RomanPerekhrest, или defaultdict
, предложенный @Ajax1234.
Ответ 6
Возможно, я скучаю по этому пункту, но по крайней мере я постараюсь помочь. Если у вас есть списки и вы хотите поместить их в dict, выполните следующие
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
lists = [a, b] # or directly -> lists = [ [1, 2, 3, 4], [5, 6, 7, 8] ]
new_dict = {}
for idx, sublist in enumerate([a, b]): # or enumerate(lists)
new_dict[idx] = sublist
надеюсь, что это поможет
Ответ 7
Было предложено использовать dict (zip (list1, list2))