Python: 字典值扁平化列表

3

我有一个类似以下的字典列表

a = [ {'list':[1,2,3]}, {'list':[1,4,5]} ]

我想要获取list键中的一组扁平化的值,如{1,2,3,4,5}。最快的方法是什么?

3个回答

4

您可以编写如下循环:

result = set()
for row in a:
    result.update(row['list'])

我认为这个方法会相当快。

或者你可以简单地使用集合推导式,这将得到以下的一行代码

result = {x for row in a for x in row['list']}

如果不是所有元素都包含 'list' 键,您可以使用带有空元组的 .get(..)(这将减少构建时间):

result = {x for row in a for x in row.get('list',())}

@SethMMorton 我同意,但我认为 set.union 可能更加简洁。 - Chris_Rands
1
@Chris_Rands:不需要给你调用set构造函数,每次构造一个空字典{}(即使不必要),并使用参数扩展。这个思路很好,但周围有很多噪音,使它不够简洁。如果.get(..)采用空元组作为默认值,则性能可以提高,因为在这种情况下,它只需传递一个引用。 - Willem Van Onsem
@WillemVanOnsem {num for b in a for x in b.values() for num in x} 在 Python 3 中可用,支持空字典和多值字典。 - TemporalWolf
1
@TemporalWolf:这是因为你在这里使用了.values()而没有使用[0]索引,因为所有的字典都只有一个值。问题在于,一旦规格略有不同,这种方法就会彻底失败。良好软件工程的一个特性是算法的健壮性:即它对规格的微小差异需要进行少量或无修改。 - Willem Van Onsem
2
@TemporalWolf: 问题:“我试图获取list键中值的平面集”。这个回答为什么是正确的? - Willem Van Onsem
显示剩余9条评论

3

不清楚你对“最快”一词的定义是什么,但无论是速度还是行数,我建议使用itertools和生成器的组合。

>>> import itertools
>>> a = [ {'list':[1,2,3]}, {'list':[1,4,5]} ]
>>> b = set(itertools.chain.from_iterable(x['list'] for x in a if 'list' in x))

请注意,我已添加了一个防止任何可能不包含'list'键的元素的保护。如果您知道这总是正确的,则可以忽略此内容。

1

通过reduce可以轻松制作平面列表。

你只需要使用初始化器——reduce函数的第三个参数。

reduce(
    lambda  _set, _dict, key='list': _set.update(
          _dict.get(key) or set()) or _set,
    a, 
    set())

上述代码适用于Python2和Python3,但您需要导入reduce模块,方式为from functools import reduce。有关详细信息,请参阅下面的链接。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接