【问题标题】:python lists - convert an existing list of lists into a dict with multiple values per key using a comprehensionpython 列表 - 使用理解将现有列表列表转换为每个键具有多个值的字典
【发布时间】:2020-10-15 13:37:47
【问题描述】:

我有一个相对简单的问题,可以通过 setdefault 轻松解决,但我现在正在自学理解,不知道如何通过理解来解决。

假设我有一个嵌套列表,其中一些内部列表具有相同的键。这意味着我应该能够生成一些键具有多个值的字典。我一直在尝试以某种方式附加这些值,但每次它只返回最后一个数字值,否则会出错。

这是一个例子:

>>> strlist
['hello w', 'hello', 'hello c', 'hello c c', 'dog']

>>> [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]
[['hello', 0], ['hello', 1], ['hello', 2], ['hello', 3], ['w', 0], ['c', 2], ['c', 3], ['dog', 4]]

我还尝试了一个元组列表、一个元组元组、一组列表、一组元组等。仍然无法让它与理解一起工作。

以下是一些失败的尝试:

>>> dict([(k,v) for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x])
{'hello': 3, 'w': 0, 'c': 3, 'dog': 4}

>>> {k:k[v] for k,v in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
Traceback (most recent call last):
  File "<pyshell#285>", line 1, in <module>
    {k:k[v] for k,v in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
  File "<pyshell#285>", line 1, in <dictcomp>
    {k:k[v] for k,v in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
IndexError: string index out of range

>>> {k:{v} for k,v in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
{'hello': {3}, 'w': {0}, 'c': {3}, 'dog': {4}}

我们的目标是:

>>> {'hello': {0, 1, 2, 3], 'w': {0}, 'c': {2, 3}, 'dog': {4}}

这甚至可以通过理解实现,还是我必须使用更常见的传统循环方法之一?

【问题讨论】:

  • 什么是strlist
  • &gt;&gt;&gt; strlist = ['hello w', 'hello', 'hello c', 'hello c c', 'dog']
  • 一行一行是强迫症吗?
  • 是的,但只是出于好奇,因为我正在学习 dict-comprehensions。

标签: python loops nested list-comprehension dictionary-comprehension


【解决方案1】:

使用您的方法将strlist 转换为列表列表,然后您可以使用collections.defaultdict

from collections import defaultdict

lst = [
    ["hello", 0],
    ["hello", 1],
    ["hello", 2],
    ["hello", 3],
    ["w", 0],
    ["c", 2],
    ["c", 3],
    ["dog", 4],
]   

d = defaultdict(set)
for x, y in lst:
    d[x].add(y)
    
print(d)
# defaultdict(<class 'set'>, {'hello': {0, 1, 2, 3}, 'w': {0}, 'c': {2, 3}, 'dog': {4}})

既然你要求词典理解:

d = {k: set(y for x, y in lst if x == k) for k, _ in lst}

【讨论】:

  • 感谢您的好提示,但我真的想看看这是否可以使用 dict-comprehension 来完成
  • @user1026169,请找到相同的。已编辑。
  • 非常感谢您的解释。这是一个完全不切实际的例子,但帮助我想象发生了什么:{k: set(y for x,y in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x] if x==k) for k,dummy_ in [[k,v] for k in set(sum([x.split() for x in strlist],[])) for v,x in enumerate(strlist) if k in x]}
  • 我只想告诉你,一行代码并不总是在所有情况下都受欢迎。更重要的是可读性。我建议分解为多行,这可能有助于您在稍后阶段进行调试。
  • 非常感谢您的澄清。这只是为了满足我对单行理解的好奇心。这些帖子帮助很大。
【解决方案2】:

这是一种使用 dict 理解在一行中完成的方法。但是,我不确定这是否是比更传统的 for 循环(使用 setdefault() 和一些临时列表等)在效率方面的最佳选择。

list_ = ['hello w', 'hello', 'hello c', 'hello c c', 'dog']
result = {
    word: {i for i, phrase in enumerate(list_) if word in phrase}
    for string in list_
    for word in string.split()
}

result的内容:

{'hello': {0, 1, 2, 3}, 'w': {0}, 'c': {2, 3}, 'dog': {4}}

【讨论】:

  • 谢谢,这有助于我更好地理解 dict-comprehensions。非常感谢。
猜你喜欢
  • 2019-05-05
  • 2021-07-01
  • 2016-12-27
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
相关资源
最近更新 更多