繁体   English   中英

列表理解中的字典

[英]Dictionary from list comprehension

我有以下清单。

arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]

我找到了字典键,这是元组中的第一项。

keys = {i[0] for i in arr_lst}
# output
# {1, 2, 3)

从那里,我创建了一个字典,如果元组中的第一项与之前定义的键匹配,则它的值是第一个列表中的元组。

id_dict = dict()
for k in keys:
    id_dict[k] = [i for i in arr_lst if i[0] == k]
# output
# {1: [(1, 34, 99)], 2: [(2, 35, 40), (2, 36, 50), (2, 37, 10)], 3: [(3, 37, 90), (3, 38, 8)]}

然后我创建了一个新列表,其元素是基于字典值的元组。 第三项在字典值中最高的元组将被附加到列表中,并删除第三项。

output_id_etak_id = []
for k, v in id_dict.items():
    m = max(v, key=lambda x: x[2])
    output_id_etak_id.append(m[:2])
# output
# [(1, 34), (2, 36), (3, 37)]

该代码有效,我得到了所需的 output。 但是,我有一个大型数据集,第一个列表中有超过 800 000 个元素,目前运行大约需要 3 个小时。 我想找到一种方法让它更快。

您可以itertools.groupby (期望排序输入)基于元组第一个元素形成组,然后 select 使用next (由@tobias-k建议)该组的第一个元素。

注意:为了使用next我们需要使用比较键x[0], -x[-1]对列表进行排序,以便形成的组按降序排列。

from itertools import groupby

arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_lst = sorted(arr_lst, key=lambda x: (x[0], -x[-1]))
result = [
    next(group)[:2]
    for key, group in groupby(arr_lst, key=lambda x: x[0])
]

键=第一个元素; 值 = 第 3 个元素的最大值的第 2 个元素

如果您想要第三个元素具有最大值的第二个元素,那么您可以使用以下代码:

arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_dict = {}
arr_temp = {}
for arr in arr_lst:
    x = arr_temp.get(arr[0],-1)
    if arr[2] > x:
        arr_temp[arr[0]] = arr[2]
        arr_dict[arr[0]] = arr[1]

arr_relist = [(k,v) for k,v in arr_dict.items()]

print (arr_relist)

output 将是:

[(1, 34), (2, 36), (3, 37)]

这样做的时机是:

For dictionary:

841 ns ± 21.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Including recreating the list with tuples:

1.18 µs ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

键=第一个元素; 值 = 第三个元素的最大值

根据评论部分,我假设您希望元组中的第一项作为键,元组中第三项的最大值作为键的值。

为此,您只需要遍历循环一次。

您的代码将是:

arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_dict = {}
for arr in arr_lst:
    x = arr_dict.get(arr[0],-1)
    if arr[2] > x: arr_dict[arr[0]] = arr[2]

print (arr_dict)

output 将是:

{1: 99, 2: 50, 3: 90}

我检查了这个时间:

792 ns ± 15.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

您可以使用itertools.groupbymap来执行此任务

import itertools
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]

def max_2_1(arr):
    maxItem = next(arr)
    for item in arr:
        if item[2] > maxItem[2]:
            maxItem = item
    return maxItem[1]
    
arr_lst.sort(key = lambda kk: kk[0]) # important as groupby rely on this
aa = map( 
    lambda keygroup: [ keygroup[0], max_2_1( keygroup[1] )  ],
    itertools.groupby(arr_lst, key=lambda item: item[0])
)   
print(list(aa)) # [[1, 34], [2, 36], [3, 37]]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM