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

Python 如何在不使用嵌套for循环的情况下将两个列表合并到字典中,python,list,dictionary,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 =

我有两份清单:

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]]
虽然这确实有效,但它效率低下,而且在列表非常大的情况下需要花费太多时间。我想知道构造这样一本词典的更优雅的方法

提前谢谢

您可以使用:

输出:

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

也许我没抓住重点,但至少我会尽力帮忙。如果你必须列出清单,并想把它们放在口述中,请执行以下操作

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
希望它有助于替代解决方案:

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

你可以通过听写理解来做到这一点:

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]}
d={k:[] for k in l}
for x,y in zip(l,l2):
   d[x].append(y)
奇怪的是,您似乎无法使用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]}

pandas
解决方案:

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)
设置: 解决方案: 演练:
  • 从输入列表创建一个
    pd.DataFrame
    a
    称为
    Group
    b
    称为
    Value
  • df.groupby('Group')
    基于
    a创建组
  • .Value.apply(list)
    获取每个组的值,并将其强制转换到
    list
  • .to_dict()
    将生成的
    DataFrame
    转换为
    dict
  • 时间: 要了解100000个组中1000000个值的测试集的时间安排,请执行以下操作:

    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

    没有花哨的结构,只是一本普通的ol'字典

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

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

    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]}
    
    d={k:[] for k in l}
    for x,y in zip(l,l2):
       d[x].append(y)
    
    现在:

    是:


    当然,我已经弄明白了你的代码是做什么的,但是用那种风格写的,它不是很明显。对于Python新手来说,我认为他们可能会发现您的代码很难理解,然后因为它而忽略(或不考虑)您的解决方案。只是一个建议,由你决定。我可以建议不要在一行中写
    结果吗?是否可以将
    groupby
    的结果作为一个单独的变量提取出来?这行太长了……这似乎比另一个答案更糟,因为你需要排序,而另一个答案没有排序,所以你的答案需要做额外的工作。@Daenyth,你的信息一点也不新。解决方案一开始就被标记为“可选”方式。如果已订购了
    list\u a
    ,则可以删除
    n log n
    排序,并且lambda会增加不必要的开销,itemgetter始终是更好的选择<代码>{k:[i for u,i in g]for k,g in groupby(zip(a,b),key=itemgetter(0))
    这是一个如何嵌套的for循环?DYM
    如果d.keys中的list_a[i]和
    d[list_a[i]=[list_b[i]
    ?请准确地发布您尝试过的代码,最好使用复制+粘贴(如果您的平台上提供)。如果提供的答案之一对您有效,请将其标记为已接受。它使将来遇到你的问题的人更容易知道什么有用。@TobySpeight
    如果
    表示如果
    列表a[i]
    已经是字典中的一个键,那么将
    列表b[i]
    添加到字典的
    列表a[i]
    下,而
    否则
    表示如果不是,则添加
    列表b[i]到新键
    list_a[i]`as list。希望能有帮助。@BigD,我想这就是你想写的(正如我建议的)list_u[a]根本没有意义,
    d[list_u[a]=
    。我建议您修复这些错误。这与OP想要的还不太接近
    a
    包含
    b
    中值的键(有些键是重复的),并且根本不使用索引。您只需使用
    列表中的索引创建
    {0:a,1:b}
    。实际上,使用
    defaultdict
    在这里是过分的。请参阅where
    dict.setdefault
    可以以最小的开销处理相同的事情。@cᴏʟᴅsᴘᴇᴇᴅ <代码>d[a].append(b)
    d.setdefault(x,[])干净得多。append(y)
    以额外导入和更重的结构为代价;-)列表是可变的,您将一个对象/列表传递给fromkeys,以便共享对单个列表/对象的引用,这与
    a=[]
    然后
    d={1:a,2:a,3:a}
    相同
    my_dict=dict.fromkeys(set(list_a),tuple());我的dict[0]+=(1,)
    将显示
    {0:(1,),1:(),9999:()}
    ,但会增加使用每个
    +=
    创建新对象/元组的开销。
    print(d)
    
    {0: [24, 53, 88], 1: [32, 45, 24, 88, 53], 9999: [1]}