【问题标题】:Python - Flatten a dict of lists into unique values?Python - 将列表的字典扁平化为唯一值?
【发布时间】:2020-03-27 04:12:04
【问题描述】:

我在 python 中有一个列表字典:

content = {88962: [80, 130], 87484: [64], 53662: [58,80]}

我想把它变成一个唯一值列表

[58,64,80,130]

我写了一个手动解决方案,但它是一个手动解决方案。我知道有更简洁和更优雅的方式来使用列表推导、 map/reduce 、 itertools 等。有人知道吗?

content = {88962: [80, 130], 87484: [64], 53662: [58,80]}
result = set({})
for k in content.keys() :
    for i in content[k]:
        result.add(i)
# and list/sort/print just to compare the output
r2 = list( result )
r2.sort()
print r2

【问题讨论】:

  • 3分钟内有4个很好的答案,都证明我需要阅读更多的标准库文档。
  • Chuckles 这种感觉永远不会消失 - 标准库中包含 很多 电池。

标签: python


【解决方案1】:

双重集合理解:

Python 3:

sorted({x for v in content.values() for x in v})

Python 2:

sorted({x for v in content.itervalues() for x in v})

【讨论】:

  • 一个指向集合理解文档的链接将使这变得完美。
  • 这真的很简洁,很好看。您可以从众多非常出色的答案中获得最佳答案。
  • 注意:这在 Python3 中不起作用,itervalues 已被删除。
  • @TomMyddeltyn 在 Python 3 中用 itervalues 代替 values(就像你用字典代替 iteritems 代替 items),因为 Python 3 支持惰性迭代
  • @Jon Clements 的回答更善于利用​​ ptyhon 标准库。
【解决方案2】:

在 python3.7 中,您可以使用.valueschain 的组合。

from itertools import chain
sorted(set(chain(*content.values())))
# [58, 64, 80, 130]

# another option is `itertools.groupby`
from itertools import groupby
[k for k, g in groupby(sorted(chain(*content.values())))]

在python2.7中

from itertools import chain
sorted(set(chain.from_iterable(content.itervalues())))
# [58, 64, 80, 130]

# another option is `itertools.groupby`
[k for k, g in groupby(sorted(chain.from_iterable(content.itervalues())))]

【讨论】:

    【解决方案3】:

    使用set()itertools.chain()

    In [83]: content = {88962: [80, 130], 87484: [64], 53662: [58,80]}
    
    In [84]: from itertools import chain
    
    In [94]: x=set(chain(*content.values()))
    
    In [95]: x
    Out[95]: set([58, 64, 80, 130]) # a set, the items may or may not be sorted
    
    In [96]: sorted(x)         #convert set to a sorted list
    Out[96]: [58, 64, 80, 130]
    

    【讨论】:

    • 很酷——不过只有几位——listsorted(list(x)) 中是多余的,而*content.values() 拼写为chain.from_iterable...
    • 我更喜欢chain(),因为它需要更少的字符,感谢sorted(list(x)) 部分。 :)
    • chain.from_iterable 不是更高效吗?仅使用链意味着您正在解包序列。而 from_iterable 在生成器中完成。
    【解决方案4】:
    sorted(set(val
                for row in content.itervalues()
                    for val in row))
    

    set 为我们获取所有不同的值(就像字典一样,但没有存储值的开销)。 sorted 然后只接受创建的set 并返回一个按升序排序的list

    【讨论】:

    • 请注意,这在 python3 中不起作用。另外,我认为这个答案比接受的答案更好地解释了列表理解。我喜欢你的格式。
    【解决方案5】:
    list(reduce(lambda a, b: a.union(set(b)), content.itervalues(), set()))
    

    lambda 将两个输入参数转换为集合并将它们合并。

    reduce 将对传递给它的列表执行left fold——在这种情况下,列表是您的字典的值。

    reduce 会将其结果(即set)转换回列表。

    这也可以拼写:

    list(reduce(lambda a, b: a | set(b), content.itervalues(), set()))
    

    【讨论】:

    • 这将在循环时创建一堆临时集。
    • 谢谢!我正在编辑以添加一些解释并意识到并(我认为)修复了它。
    • 在我看来,a.union(set(b) 更明确且更具可读性。 a | set (b) 当然也可以。
    【解决方案6】:
    sorted(set(sum(content.values(), [])))
    

    【讨论】:

      【解决方案7】:

      使用列表推导生成非唯一列表,将其转换为集合以获取唯一值,然后返回排序列表。也许不是最有效的,但又是另一种单行解决方案(这次没有导入)。

      Python 3:

      sorted(list(set([val for vals in content.values() for val in vals])))
      

      Python 2.7:

      sorted(list(set([val for vals in content.itervalues() for val in vals])))
      

      【讨论】:

      • 这应该是利用列表/字典理解的最优雅的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-24
      • 2019-02-04
      • 1970-01-01
      • 2022-01-17
      • 1970-01-01
      • 2017-02-27
      • 2019-04-23
      相关资源
      最近更新 更多