【问题标题】:Dictionary Comprehension in Python for key:[1,2,3] [duplicate]Python中键的字典理解:[1,2,3] [重复]
【发布时间】:2023-03-10 13:01:01
【问题描述】:

虽然我一直在提高我的 Python 技能,但我有一个问题。 我的代码如下:

# def invertDictionary(dict):
#     new_dict = {} 
#     for key, value in dict.items():
#                 if value in new_dict:
#                         new_dict[value].append(key) 
#                 else: 
#                     new_dict[value]=[key]
#     return new_dict

def invertDictionary(dict):
    new_dict = {value:([key] if value else [key]) for key, value in dict.items()}
    return new_dict;

invertDictionary({'a':3, 'b':3, 'c':3})

我正在尝试获得像 {3:['a','b','c']} 这样的输出。我已经使用普通的for循环实现了这一点;我只想知道如何使用 Dictionary Comprehension 获得这些结果。我试过但附加它得到一个错误。请让我知道如何实现这一目标。 提前致谢!

【问题讨论】:

  • 我不认为你可以通过 dict 理解来做到这一点,但你可以通过使用 collections.defaultdict 或执行类似 new_dict.setdefault(value, []).append(key) 的操作来摆脱函数中的 if ... else ... 语句。
  • 如果没有某种预先占有,就没有优雅的理解方式
  • 这是可能的,但它迫使你使用一种可能效率低下的方法,得到一个二次时间算法,而天真的 for 循环方法会给你线性时间。
  • @juanpa.arrivillaga 我会说copperfield's 是不错的(至少不是黑客)而且也是次二次的。

标签: python python-3.x


【解决方案1】:

您错过了需要列表理解来构建列表。
遍历 dict 中的值,并为每个值构建所需的键列表。

请注意,这是一个二次过程,而规范(且更易读)for 循环是线性的。

d = {'a':3, 'b':3, 'c':3, 'e':4, 'f':4, 'g':0}
inv_dict = {v: [key for key, val in d.items() if val == v]
               for v in set(d.values())}

结果:

{0: ['g'],
 3: ['a', 'b', 'c'],
 4: ['e', 'f']
}

这样可以吗?

【讨论】:

  • 正如 juanpa.arrivillaga 所提到的,这是二次时间,这使得它比直接的 for 循环更糟糕。
  • @user2357112supportsMonica 不管它的效率如何,它肯定回答了这个问题。
  • @M-Chen-3 Stack Overflow 不是一个盲目分发代码的地方。如果您发布的答案具有明显的劣势,则应改进答案以注意该劣势。有时,当有人问“我怎么打自己的脚”时,我们需要回答“嗯,你真的不应该打自己的脚(但如果你真的想要,你可以在这里扣动扳机...)"
  • 确实说这是非线性的。
  • @Prune 是的,也许对措辞稍作修改,使用“非线性时间算法”来说明清楚。我觉得“非线性过程”有点模棱两可
【解决方案2】:

虽然带有常规 for 循环的原始版本是解决此问题的最佳解决方案,但这里是 @Prune 答案的变体,不会多次遍历字典

>>> import itertools
>>> d = {'a':3, 'b':3, 'c':3, 'e':4, 'f':4, 'g':0}
>>> {group_key:[k for k,_ in dict_items] 
     for group_key,dict_items in itertools.groupby(
                                             sorted(d.items(),key=lambda x:x[-1]),
                                             key=lambda x:x[-1]
                                             )
      }
{0: ['g'], 3: ['a', 'b', 'c'], 4: ['e', 'f']}
>>> 

首先我们使用lambda function 使用lambda function 的键函数对dict 的项目按值排序,以提取项目元组的值部分,然后我们使用groupby 将具有相同值的那些分组加上相同的键功能,最后用列表理解提取键

--

正如 Kelly 所说,我们可以使用 dict 中的 get 方法来获取值以使其更短,并利用对 dict 的迭代为您提供其键的事实

>>> {k: list(g) for k, g in itertools.groupby(sorted(d, key=d.get), d.get)}
{0: ['g'], 3: ['a', 'b', 'c'], 4: ['e', 'f']}
>>> 

【讨论】:

  • 好主意。较短的版本:{k: list(g) for k, g in itertools.groupby(sorted(d, key=d.get), d.get)}
  • @Copperfield 谢谢它非常好的解决方案.. :)
【解决方案3】:

您可以使用defalutdictappend 方法。

from collections import defaultdict

dict1 = {'a': 3, 'b': 3, 'c': 3}
dict2 = defaultdict(list)
{dict2[v].append(k) for k, v in dict1.items()}

dict2
>>> defaultdict(list, {3: ['a', 'b', 'c']})

【讨论】:

  • 这不是字典理解,甚至不是滥用。
  • 不要使用理解结构来产生副作用
  • @juanpa.arrivillaga 感谢您的建设性反馈。
  • @TimothyHelton 是的,不幸的是,这就像 python 标签上的大罪,所以它是一个不受欢迎的磁铁。我不会为此感到太难过,很多人都这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-05
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
  • 1970-01-01
相关资源
最近更新 更多