0

我想写一个字典理解。协助与词典理解

我有这样一个字典:

main_dict = { 
    'A' : {'key1' : 'valueA1', 'key2' : 'valueA2'}, 
    'B' : {'key2' : 'valueB2', 'key3' : 'valueB3'}, 
    'C' : {'key3' : 'valueC3', 'key1' : 'valueC1'}} 

我想执行以下逻辑:

d = {} 
for k_outer, v_outer in main_dict.items(): 
    for k_inner, v_inner in v_outer.items(): 
     if k_inner in d.keys(): 
      d[k_inner].append([k_outer, v_inner]) 
     else: 
      d[k_inner] = [[k_outer, v_inner]] 

其产生以下结果:

{'key3': [['C', 'valueC3'], ['B', 'valueB3']], 
'key2': [['A', 'valueA2'], ['B', 'valueB2']], 
'key1': [['A', 'valueA1'], ['C', 'valueC1']]} 

(我知道我可以使用defaultdict(list)但这只是一个例子)

我想用一个字典,理解到执行逻辑,所以到目前为止,我有以下几点:

d = {k : [m, v] for m, x in main_dict.items() for k, v in x.items()} 

这是不行的,它只是给了我下面的输出:

{'key3' : ['B', 'valueB3'], 
'key2' : ['B', 'valueB2'], 
'key1' : ['C', 'valueC1']} 

哪是为每个inner_key找到的最后一个实例...

我迷失如何正确执行这种嵌套的列表理解。我尝试了多种变化,比最后一次更糟糕。

+3

为清楚起见,你能告诉我们你希望你的例子输入输出? –

+1

你确定把所有这些逻辑都用在词典理解中是个好主意吗?有时可读性比几行代码更好。 – pemistahl

+1

@PeterStahl很显然你以前没有 –

回答

0

,这是我使用的:

from collections import defaultdict 

d = defaultdict(list) 
for m, x in main_dict.items(): 
    for k, v in x.items(): 
     d[k].append((m, v)) 
2

你可以尝试这样的事情:

In [61]: main_dict 
Out[61]: 
{'A': {'key1': 'valueA1', 'key2': 'valueA2'}, 
'B': {'key2': 'valueB2', 'key3': 'valueB3'}, 
'C': {'key1': 'valueC1', 'key3': 'valueC3'}} 

In [62]: keys=set(chain(*[x for x in main_dict.values()])) 

In [64]: keys 
Out[64]: set(['key3', 'key2', 'key1']) 

In [63]: {x:[[y,main_dict[y][x]] for y in main_dict if x in main_dict[y]] for x in keys} 
Out[63]: 
{'key1': [['A', 'valueA1'], ['C', 'valueC1']], 
'key2': [['A', 'valueA2'], ['B', 'valueB2']], 
'key3': [['C', 'valueC3'], ['B', 'valueB3']]} 

更可读的解决方案使用dict.setdefault

In [81]: d={} 

In [82]: for x in keys: 
    for y in main_dict: 
     if x in main_dict[y]: 
      d.setdefault(x,[]).append([y,main_dict[y][x]]) 
    ....:    

In [83]: d 
Out[83]: 
{'key1': [['A', 'valueA1'], ['C', 'valueC1']], 
'key2': [['A', 'valueA2'], ['B', 'valueB2']], 
'key3': [['C', 'valueC3'], ['B', 'valueB3']]} 
+2

换句话说,把它留作循环。 –

+0

这是一个有趣的想法 - 首先提取密钥,它可以全部在一行中完成,但它仍然意味着通过两次'main_dict'键迭代。而我上面发布的'长'方法一次完成整个事情。我确信有一种方法可以有效地使用字典理解和一次传递,只需要找到它。 –

1

采用三名字典解析来实现这样的任务,第三字典,理解是要结合前两个字符:

e = {k : [m, v] for m, x in main_dict.items() for k, v in x.items()} 
f = {k : [m, v] for m, x in main_dict.items() for k, v in x.items() if [m,v] not in e.values()} 
g = {k1 : [m, v] for k1,m in e.items() for k2,v in f.items() if k1==k2} 
+1

当然,如果你真的想让任何人都不可能再读一遍,你就可以将这整个事物合并成一个巨大的嵌套理解。 :) – abarnert

+0

我写这个只是为了展示pythonic方式和字典理解的微妙之处。 – mayaa

+0

我发布的样本词典仅仅是一个示例/实例,真正的词典有更多的条目,这种解决方案不会工作 - 如果它被改编(即每个条目更多的词典),这将是非常低效的。 –

0

One opti在是利用itertools.groupby

from itertools import groupby 
from operator import itemgetter 

main_dict = { 
    'A' : {'key1' : 'valueA1', 'key2' : 'valueA2'}, 
    'B' : {'key2' : 'valueB2', 'key3' : 'valueB3'}, 
    'C' : {'key3' : 'valueC3', 'key1' : 'valueC1'}} 

## Pull inner key, outer key and value and sort by key (prior to grouping) 
x = sorted([(k2, [k1, v2]) for k1, v1 in main_dict.items() for k2, v2, in v1.items()]) 

## Group by key. This creates an itertools.groupby object that can be iterated 
## to get key and value iterables 
xx = groupby(x, key=itemgetter(0)) 

for k, g in xx: 
    print('{0} : {1}'.format(k, [r[1] for r in list(g)])) 

根据您的数据和性能要求,整理可能不理想所以它的价值分析。

此外,它不会导致指定的字典,而是一个groupby对象。这可能是“类似于字典”的,足以满足您的需求;迭代它会产生关键和迭代。

到底
+0

但是我怎样才能像字典一样使用这个数据结构呢? –

+0

通过迭代的方式如图所示,并根据需要使用键和值列表,或迭代它并将其放入字典中。如果你真的需要字典,也许这不是一个合适的解决方案。 –