是否有更快或更多" pythonic"实现这一目标的方法:
dicta = {'a':{'a1':1, 'a2':2}, 'b':{'b1': 1, 'b2': 2}}
dictb = {'b':{'b1':1, 'a2':2}, 'c':{'c1': 1, 'c2': 2}}
dictc = {}
dictc.update(dicta)
for outside_key in dictb:
if outside_key in dictc:
for inside_key in dictb[outside_key]:
if inside_key in dictc[outside_key]:
dictc[outside_key][inside_key] += dictb[outside_key][inside_key]
else:
dictc[outside_key][inside_key] = dictb[outside_key][inside_key]
else:
dictc[outside_key] = dictb[outside_key]
dictc现在包含以下内容:
{'a': {'a1': 1, 'a2': 2},
'c': {'c2': 2, 'c1': 1},
'b': {'a2': 2, 'b1': 2, 'b2': 2}}
我在django模型定义中使用它,上面似乎是描述问题最明显的方法,但后来我意识到它不够具体。
这是django代码的样子:
def get_capabilities(self):
capabilities_dict = {}
capabilities_list = ('card', 'module') #Two ManyToMany fields
capabilities_dict.update(self.barebone.get_capabilities())
# self.barebone.get_capabilities() is the only foreingkey field
# and serves as the base on which we build the capabilities list.
for capability in capabilities_list:
instances = getattr(self, capability).all()
for instance in instances:
capabilities = instance.get_capabilities()
for capability_name in capabilities:
if capability_name in capabilities_dict:
for obj in capabilities[capability_name]:
if obj in capabilities_dict[capability_name]:
capabilities_dict[capability_name][obj] += capabilities[capability_name][obj]
else:
capabilities_dict[capability_name][obj] = capabilities[capability_name][obj]
else:
capabilities_dict[capability_name] = capabilities[capability_name]
return capabilities_dict
self.barebone.get_capabilities()看起来像这样:
{'compatible_bus_types': {<BusType: PCI-X>: 1},
'compatible_storage_interfaces': {<StorageInterface: SATA>: 8},
'compatible_storage_form_factors': {<StorageFormFactor: 3.5">: 4}}
并且上面的函数get_capabilities()返回:
{'compatible_network_connectors': {},
'compatible_storage_interfaces': {<StorageInterface: SATA>: 8,
<StorageInterface: SAS>: 8},
'compatible_network_standards': {},
'compatible_storage_form_factors': {<StorageFormFactor: 3.5">: 4},
'compatible_bus_types': {<BusType: PCI-X>: 1},
'compatible_network_form_factors': {}}
每个&lt;&gt;封闭的&#34;内键&#34;实际上是另一个模型实例。
谢谢,
答案 0 :(得分:3)
将collections.Counter
与普通字典一起使用:
>>> from collections import Counter
>>> dictc = {}
>>> for d in (dicta, dictb):
for k, v in d.items():
dictc[k] = dictc.get(k, Counter()) + Counter(v)
...
>>> dictc
{'a': Counter({'a2': 2, 'a1': 1}),
'c': Counter({'c2': 2, 'c1': 1}),
'b': Counter({'a2': 2, 'b1': 2, 'b2': 2})}
或使用defaultdict
:
>>> from collections import Counter, defaultdict
>>> dictc = defaultdict(Counter)
>>> for d in (dicta, dictb):
for k, v in d.items():
dictc[k] += Counter(v)
...
>>> dictc
defaultdict(<class 'collections.Counter'>,
{'a': Counter({'a2': 2, 'a1': 1}),
'c': Counter({'c2': 2, 'c1': 1}),
'b': Counter({'a2': 2, 'b1': 2, 'b2': 2})})
答案 1 :(得分:0)
您使用嵌套的dict
,但我认为有一个更简单的数据结构:您可以使用元组,例如('a','a2')
作为键而不是。你的dicts看起来像这样:
dicta = {('a', 'a1'): 1, ('a', 'a2'): 2, ('b', 'b1'): 1, ('b', 'b2'): 2}
dictb = {('b', 'a2'): 2, ('b', 'b1'): 1, ('c', 'c1'): 1, ('c', 'c2'): 2}
访问这些值的方法如下:
print dicta['a', 'a1']
Out: 1
而不是
print dicta['a']['a1']
Out: 1
要将数据更改为该结构,您可以使用此功能:
def unnestdict(dct):
return { (key1, key2):value
for key1, sub_dct in dct.iteritems()
for key2, value in sub_dct.iteritems()}
如果您使用此数据结构,则可以轻松使用Counter
中的collections
- 类 - 模块:
from collections import Counter
counterC = Counter(dicta) + Counter(dictb)
print counterC
Out: Counter({('b', 'b2'): 2, ('a', 'a2'): 2, ('b', 'b1'): 2, ('b', 'a2'): 2, ('c', 'c2'): 2, ('a', 'a1'): 1, ('c', 'c1'): 1})
dictc = dict(counterC)
print dictc
Out: {('b', 'a2'): 2, ('b', 'b1'): 1, ('c', 'c1'): 1, ('c', 'c2'): 2}