嵌套在Dict理解中的Python集合理解

时间:2017-11-13 21:04:24

标签: python nested dictionary-comprehension set-comprehension

我有一个元组列表,其中每个tuple包含一个string和一个以下形式的数字:

[(string_1, num_a), (string_2, num_b), ...]

字符串不是唯一的,数字也是如此,例如<{1}}或(string_1 , num_m)可能存在于列表中。

我尝试创建一个以字符串作为键的字典,以及一组以字符串形式出现的所有数字作为值:

(string_9 , num_b)

通过嵌套集合理解,我已经成功地完成了以下字典理解:

dict = {string_1: {num_a, num_m}, string_2: {num_b}, ...}

只有一个问题:#st_id_list = [(string_1, num_a), ...] #st_dict = {string_1: {num_a, num_m}, ...} st_dict = { st[0]: set( st_[1] for st_ in st_id_list if st_[0] == st[0] ) for st in st_id_list } 长达18,000项。这段代码运行500个元组的列表只需不到10秒,但运行完整的18,000个元组需要12分钟以上。我必须认为这是因为我在词典理解中嵌套了一套理解。

有没有办法避免这种情况,或者更聪明的方法呢?

2 个答案:

答案 0 :(得分:9)

你有一个双循环,所以你需要O(N ** 2)时间来制作你的字典。对于500件物品,需要250.000步骤,而对于18k物品,需要完成324 百万步骤。

这是一个O(N)循环,因此对于较小的数据集需要500步,对于较大的数据集需要18.000步:

st_dict = {}
for st, id in st_id_list:
    st_dict.setdefault(st, set()).add(id)

这使用dict.setdefault() method来确保对于给定的键(您的字符串值),如果缺少键,则至少有一个空集可用,然后将当前id值添加到该值集。

您可以使用collections.defaultdict() object

执行相同操作
from collections import defaultdict

st_dict = defaultdict(set)
for st, id in st_id_list:
    st_dict[st].add(id)

defaultdict()使用传入的工厂为缺失的密钥设置默认值。

defaultdict方法的缺点是对象继续以在循环之后为缺失键生成默认值,这可以隐藏应用程序错误。使用st_dict.default_factory = None显式禁用工厂以防止这种情况发生。

答案 1 :(得分:0)

为什么你在这样的循环中使用两个循环:

list_1=[('string_1', 'num_a'), ('string_2', 'num_b'),('string_1' , 'num_m'),('string_9' , 'num_b')]

string_num={}
for i in list_1:
    if i[0] not in string_num:
        string_num[i[0]]={i[1]}
    else:
        string_num[i[0]].add(i[1])

print(string_num)

输出:

{'string_9': {'num_b'}, 'string_1': {'num_a', 'num_m'}, 'string_2': {'num_b'}}