如何在不使用嵌套for循环的情况下将两个列表合并到字典中

时间:2017-10-31 22:07:30

标签: python list dictionary

我有两个清单:

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]]

虽然这确实有效,但效率很低,而且当列表非常大时会占用太多时间。我想知道更优雅的方法来构建这样的字典吗?

提前致谢!

7 个答案:

答案 0 :(得分:30)

您可以使用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]}

答案 1 :(得分:13)

替代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]}

答案 2 :(得分:5)

没有奇特的结构,只是一个简单的结构。字典。

d = {}
for x, y in zip(a, b):
    d.setdefault(x, []).append(y)

答案 3 :(得分:4)

你可以用dict理解来做到这一点:

counts = {"worm": 0, "guest": 0, "anonymous": 0}
for line in myfile:
    for word in counts:
        if word in line:
            counts[word] += 1

奇怪的是,你似乎无法使用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), [])

答案 4 :(得分:3)

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]}

操作实例:

  1. 从输入列表中创建pd.DataFramea称为Groupb称为Value
  2. df.groupby('Group')根据a
  3. 创建群组
  4. .Value.apply(list)获取每个组的值并将其转换为list
  5. .to_dict()会将生成的DataFrame转换为dict
  6. 定时:

    了解100,000个组中1,000,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)
    

    但说实话,它可能不如@RomanPerekhrest建议的itertools.groupby或@ Ajax1234建议的defaultdict效率低。

答案 5 :(得分:2)

也许我错过了这一点,但至少我会尽力帮助。如果你必须列出并希望将它们放入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

希望有所帮助

答案 6 :(得分:0)

或者事先进行字典理解,然后由于所有键都具有空列表的值,因此要遍历两个列表的zip,然后将第二个列表的值添加到字典的键中以命名第一个列表的值,否由于预先的字典理解,需要try-except子句(或if语句)来查看键是否存在:

d={k:[] for k in l}
for x,y in zip(l,l2):
   d[x].append(y)

现在:

print(d)

是:

{0: [24, 53, 88], 1: [32, 45, 24, 88, 53], 9999: [1]}