【问题标题】:Assist with dict comprehension协助听写理解
【发布时间】:2012-12-20 08:06:27
【问题描述】:

我正在尝试编写字典理解。

我有一本这样的字典:

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),但这只是一个例子)

我想使用 dict-comprehension 执行逻辑,到目前为止我有以下内容:

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 找到的最后一个实例是什么...

我不知道如何正确执行此嵌套列表理解。我尝试了多种变体,都比上一个差。

【问题讨论】:

  • 为清楚起见,您能否向我们展示您对示例输入的期望输出?
  • 您确定将所有这些逻辑放入字典理解中是个好主意吗?有时可读性胜过几行代码。
  • @PeterStahl 你显然没玩过Code Golf
  • @AlexL 好吧,如果只是为了打高尔夫球,那也没关系。 ;)
  • 为什么这被标记为“性能”?您是想获得最快的版本,还是使用最少临时内存的版本?

标签: python performance list-comprehension dictionary-comprehension


【解决方案1】:

你可以试试这样的:

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']]}

【讨论】:

  • 换句话说,将其保留为循环。
  • 这是一个有趣的想法——首先提取密钥,它可以在一行中完成,但它仍然意味着迭代 main_dict 密钥两次。而我在上面发布的“长”方法一次性完成了整个事情。我确信有一种方法可以有效地使用 dict-comprehension 和 one-pass,只需要找到它。
【解决方案2】:

使用三个字典理解来完成这样的任务,第三个字典理解是结合前两个字典:

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}

【讨论】:

  • 可以将整个内容组合成一个庞大的嵌套理解,当然,如果您真的想让任何人都无法再次阅读。 :)
  • 我写这个只是为了展示一种pythonic方式和dict-comprehension的微妙之处。
  • 我发布的示例字典只是一个示例/示例,真正的字典有更多条目,此解决方案将不起作用 - 如果要对其进行调整(即每个条目有更多字典)它效率会很低。
【解决方案3】:

一种选择是使用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)]))

根据您的数据和性能要求,排序可能并不理想,因此值得进行分析。

此外,它不会产生指定的 dict,而是 groupby 对象。这可能足以满足您的需求;迭代它会产生 key 和 iterables。

【讨论】:

  • 但是我怎样才能像字典一样使用这个数据结构呢?
  • 要么通过迭代如图所示并根据需要使用键和值列表,要么通过迭代并将其放入字典中。如果你真的需要一个 dict,也许这不是一个合适的解决方案。
【解决方案4】:

最后,这是我用的:

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))

【讨论】:

    猜你喜欢
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多