【问题标题】:Python consolidate dictionary keys and values using comprehensionPython使用理解合并字典键和值
【发布时间】:2017-12-16 09:18:19
【问题描述】:

如何使用 python COMPRHENSION 整合以下内容

FROM(字典列表)

[
 {'server':'serv1','os':'Linux','archive':'/my/folder1'}
 ,{'server':'serv2','os':'Linux','archive':'/my/folder1'}
 ,{'server':'serv3','os':'Linux','archive':'/my/folder2'}
 ,{'server':'serv4','os':'AIX','archive':'/my/folder1'}
 ,{'server':'serv5','os':'AIX','archive':'/my/folder1'}
]

TO(以元组为键的字典列表和以“服务器#”为值的列表

[
 {('Linux','/my/folder1'):['serv1','serv2']}
 ,('Linux','/my/folder2'):['serv3']}
 .{('AIX','/my/folder1'):['serv4','serv5']}
]

【问题讨论】:

  • 理解并不是这项工作的真正工具......

标签: python dictionary list-comprehension consolidation


【解决方案1】:

需要能够为您的字典设置默认值并多次使用相同的键可能会使 dict-comprehension 有点笨拙。我更喜欢这样的:

defaultdict 可能会有所帮助:

from collections import defaultdict

lst = [
 {'server':'serv1','os':'Linux','archive':'/my/folder1'},
 {'server':'serv2','os':'Linux','archive':'/my/folder1'},
 {'server':'serv3','os':'Linux','archive':'/my/folder2'},
 {'server':'serv4','os':'AIX','archive':'/my/folder1'},
 {'server':'serv5','os':'AIX','archive':'/my/folder1'}
]

dct = defaultdict(list)

for d in lst:
    key = d['os'], d['archive']
    dct[key].append(d['server'])

如果您希望最后有一个标准字典(实际上我并没有看到一个很好的理由),您可以使用dict.setdefault 来创建一个键尚不存在的空列表:

dct = {}

for d in lst:
    key = d['os'], d['archive']
    dct.setdefault(key, []).append(d['server'])

documentation on defaultdict (vs. setdefault):

这种技术比同等技术更简单、更快捷 使用 dict.setdefault()

【讨论】:

  • 没有使用列表推导,但我认为由于累积效应,没有办法使用列表推导来做到这一点。
  • 你有证据证明它更快吗?
  • @Jean-FrançoisFabre 试图先找到一个具有理解能力的版本,但需要设置一个默认值是很棘手的......将对此添加备注。
  • @shadow 这是官方 python 文档所说的。你做了基准测试吗?
  • 只是一个指向文档说明的链接就足够了。
【解决方案2】:

由于累积效应,列表理解很难实现。但是,可以在按您的键排序的列表中使用itertools.groupby(对排序和分组使用相同的key 函数)。

然后在列表理解中提取服务器信息并按组键作为前缀。将结果(组键、服务器列表)传递给字典理解,然后就可以了。

import itertools

lst = [
 {'server':'serv1','os':'Linux','archive':'/my/folder1'}
 ,{'server':'serv2','os':'Linux','archive':'/my/folder1'}
 ,{'server':'serv3','os':'Linux','archive':'/my/folder2'}
 ,{'server':'serv4','os':'AIX','archive':'/my/folder1'}
 ,{'server':'serv5','os':'AIX','archive':'/my/folder1'}
]


sortfunc = lambda x : (x['os'],x['archive'])

result = {k:[x['server'] for x in v] for k,v in itertools.groupby(sorted(lst,key=sortfunc),key = sortfunc)}


print(result)

我明白了:

{('Linux', '/my/folder1'): ['serv1', 'serv2'], ('AIX', '/my/folder1'): ['serv4', 'serv5'], ('Linux', '/my/folder2'): ['serv3']}

请记住,并不是因为它可以写成一行就更有效。例如,defaultdict 方法不需要排序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 1970-01-01
    • 2022-12-12
    • 2018-10-04
    相关资源
    最近更新 更多