python - 如何简化这些字典理解?

标签 python python-3.x dictionary list-comprehension dictionary-comprehension

下面的代码正在运行并带来了我想要的结果。但是,有两组两个字典理解,我无法将其转换为两个字典理解。这可能吗?

dicTfAll={1:{'c1': ['aa','bb','cc']},
         2:{'c1': ['dd','ee','ff']}}


dicTf={1:{'c2': ['aax','bbx','cc']},
         2:{'c2': ['ddy','eey','ff']},
         3: {'c2': ['xx', '11']}}

allKeys=list(dicTfAll.keys())
dicTfAllP1={item[0]:item[1]  for item in dicTf.items() if item[0] not in allKeys}
dicTfAllP2={item[0]:dict(dicTfAll[item[0]],**item[1])  for item in dicTf.items() if item[0] in allKeys}
dicTfAllP=dicTfAllP1
dicTfAllP.update(dicTfAllP2)
# I use at this point dicTfAllP to do a lot of calculations. 
# dicTfAllP has the same form but very different values. 
allKeys=list(dicTfAllP.keys())
listOfCompanies=['c1','c2']
outputCompanies={}
for company in listOfCompanies:
    theKeys=[key for key in allKeys if company in dicTfAllP[key]]
    outputCompanies[company]={token:key  for key in theKeys for token in dicTfAllP[key][company]}

准确地说,我想将下面的这些行转换为一个字典理解[它生成一个嵌套字典,它是上述字典的合并]:

allKeys=list(dicTfAll.keys())
dicTfAllP1={item[0]:item[1]  for item in dicTf.items() if item[0] not in allKeys}
dicTfAllP2={item[0]:dict(dicTfAll[item[0]],**item[1])  for item in dicTf.items() if item[0] in allKeys}

此外,我想将下面的这些行也转换为一个字典理解[它构建一个嵌套字典来恢复原始字典(合并之前)]:

outputCompanies={}
for company in listOfCompanies:
    theKeys=[key for key in allKeys if company in dicTfAllP[key]]
    outputCompanies[company]={token:key  for key in theKeys for token in dicTfAllP[key][company]}

我特别担心执行的效率。如果我需要保留这种结构该怎么办? 我确实必须保留这个结构,因为我必须在两组字典理解之间进行大量计算。

最佳答案

推导式是 Python 的一个令人惊叹的功能,但它们并不总是最好的情况。与其创建大量变量并将它们混在一起,不如一次处理一个变量可能会更好。我确信可以从这段代码中榨取更多的汁液,但这应该提供可读性和处理能力的良好平衡。我检查了输出以确保它与您的代码的输出匹配。

dicTfAll = {
    1: {'c1': ['aa', 'bb', 'cc']},
    2: {'c1': ['dd', 'ee', 'ff']}
}

dicTf = {
    1: {'c2': ['aax', 'bbx', 'cc']},
    2: {'c2': ['ddy', 'eey', 'ff']},
    3: {'c2': ['xx', '11']}
}

outputCompanies = {}

for d in [dicTfAll, dicTf]:
    for idx, records in d.items():
        for company, items in records.items():

            if company not in outputCompanies.keys():
                outputCompanies[company] = {}

            for item in items:
                outputCompanies[company][item] = idx

print(outputCompanies)
# {
#     'c2': {'11': 3, 'ddy': 2, 'eey': 2, 'cc': 1, 'xx': 3, 'ff': 2, 'bbx': 1, 'aax': 1}, 
#     'c1': {'aa': 1, 'bb': 1, 'cc': 1, 'dd': 2, 'ee': 2, 'ff': 2}
# }

由于您正在寻找性能更高的代码,因此这里是使用 %%timeit 的运行时比较在 jupyter 实验室。

# My version
2.99 µs ± 30 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)


# Original Version
6.39 µs ± 25.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

我还尝试了稍微更紧凑的代码版本,但最终运行时间更长。

%%timeit
outputCompanies = defaultdict(dict)

for d in [dicTfAll, dicTf]:
    for idx, records in d.items():
        for company, items in records.items():
            outputCompanies[company].update({item: idx for item in items})

# 4.88 µs ± 22.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

另一个实际上包含理解的测试:

%%timeit
outputCompanies = {}

for d in [dicTfAll, dicTf]:
    for idx, records in d.items():
        for company, items in records.items():

            if company not in outputCompanies.keys():
                outputCompanies[company] = {}

            outputCompanies[company].update({
                item: idx for item in items
            })
# 4.99 µs ± 23.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

对于您的代码的一些评论,dict.keys()返回 list对象,因此无需调用 list(dict.keys()) 。也无需创建变量 allKeys因为您可以调用 dict.keys()在你的字典理解中。公司是硬编码的,如果这是一次性脚本,那么这很好,但如果您希望数据集随着时间的推移而扩展,则不是最好的。但如果您想对它们进行硬编码,您可以跳过变量声明并只需输入 for company in ['c1','c2']: 。接下来,您可以通过创建 dicTfAllP 来保存更多变量等于第一个理解,然后用第二个理解更新它。将它们放在一起,您将得到以下代码。它更具可读性,也更容易理解,但性能并没有更高。

%%timeit
dicTfAllP = {
    item[0]:item[1]
    for item 
    in dicTf.items()
    if item[0] not in dicTfAll.keys()
}

dicTfAllP.update({
    item[0]: dict(dicTfAll[item[0]], **item[1])
    for item 
    in dicTf.items() 
    if item[0] in dicTfAll.keys()
})

outputCompanies = {}
for company in ['c1','c2']:
    theKeys = [key for key in dicTfAllP.keys() if company in dicTfAllP[key]]
    outputCompanies[company] = {
        token:key
        for key in theKeys 
        for token in dicTfAllP[key][company]
    }
# 6.11 µs ± 58.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

关于python - 如何简化这些字典理解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59807223/

相关文章:

Python数据框sume迭代

python - 防止 TableView 标题突出显示

python - 按字典中的值过滤项目

python - 有没有办法通过一个请求仅列出 Google Drive API 上根文件夹或根文件夹下任何级别的文件?

python - 我的字典有什么问题(将值映射到卡片)

python - 在 Python 类中使用 self(在 Nuke 中制作 GUI)

python - 鸡蛋和零件之间的构建有什么区别?

python - 有没有像 Django gems - plugins 这样的东西,就像有 Ruby gems 一样

python - 根据条件从嵌套字典中删除子字典

java - 如何更新 map 中的 map ?