Python - 根据多个键过滤字典列表

8

假设我有一个字典:

myDict = [{'first': 'James', 'middle': 'Smith', 'last': 'Joule'}, 
        {'first': 'James', 'middle': 'Johnson', 'last': 'Watt'},
        {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'}
        {'first': 'Robert', 'last': 'Antonio'}]

我有一个名为keys的列表:

keys = ["middle", "last"]

我希望能根据keys中的每个值过滤myDict,这将导致:
filteredDict = [{'middle': 'Smith', 'last': 'Joule'},
              {'middle': 'Johnson', 'last': 'Watt'},
              {'middle': 'Edward', 'last': 'Doppler'},
              {'last': 'Antonio'}]

如在myDict列表中的字典列表中所示,字典不必同时具有两个键才能被放入filteredDict中。是否有一种简单的方式可以使用Python中的字典推导来实现这一点?

2个回答

17

使用列表推导式:

myDict = [{'first': 'James', 'middle': 'Smith', 'last': 'Joule'}, 
      {'first': 'James', 'middle': 'Johnson', 'last': 'Watt'},
      {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'},
      {'first': 'Robert', 'last': 'Antonio'}]

keys = {"middle", "last"}

l = [{k:v for k, v in i.items() if k in keys} for i in myDict]

但你也可以使用map函数来实现这个功能:

myDict = [{'first': 'James', 'middle': 'Smith', 'last': 'Joule'}, 
      {'first': 'James', 'middle': 'Johnson', 'last': 'Watt'},
      {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'},
      {'first': 'Robert', 'last': 'Antonio'}]

keys = {"middle", "last"}

l = list(map(lambda x: {k:v for k, v in x.items() if k in keys}, myDict))
print(l)

输出:

[{'last': 'Joule', 'middle': 'Smith'}, {'last': 'Watt', 'middle': 'Johnson'}, {'last': 'Doppler', 'middle': 'Edward'}, {'last': 'Antonio'}]

我只会将“keys”转换为“set” - 以加快查找速度。 - volcano
4
使用列表推导式代替map可以让代码看起来更简洁。因此,只需写成[{ k: v for (k,v) in x.items() if k in keys } for x in myDict]。请注意,这不会改变原始代码的含义。 - K. A. Buhr
顺便说一下,“map”是另一种推导形式。由于在Python 3中它生成了迭代器“map object”,因此,推导式将成为通用选择。 - volcano
工作完美,只是想检查哪个需要更少的时间来执行。 - akash karothiya
@K.A.Buhr 你是对的,但出于某种原因,我在 map 之后才想到这个问题。 - neverwalkaloner
键值不应该是一个列表吗,@op? - ScipioAfricanus

1

如果您只需要做一次,那么请使用neverwalkaloner的答案。但是,如果您经常操作字典列表,则我编写了一个名为PLOD的免费库,可简化大部分操作。

>>> from PLOD import PLOD
>>> l = PLOD(myDict).dropKey("middle").returnList()
>>> l
[{'last': 'Joule', 'first': 'James'}, {'last': 'Watt', 'first': 'James'}, {'last': 'Doppler', 'first': 'Christian'}, {'last': 'Antonio', 'first': 'Robert'}]
>>> print(PLOD(l).returnString())
[
    {first: 'James'    , last: 'Joule'  },
    {first: 'James'    , last: 'Watt'   },
    {first: 'Christian', last: 'Doppler'},
    {first: 'Robert'   , last: 'Antonio'}
]
>>> 

这个库可以在PyPi上找到: https://pypi.python.org/pypi/PLOD

为了更普遍地实现你想要的功能,我需要添加一个新的类方法。也许是.filterKeys。也许我会在1.8版本中这样做。然后它会变成这样:

>>> l = PLOD(myDict).filterKeys(['first', 'last']).returnList()

嗯...

顺便提一下,该库目前支持Python 2.7.x。我们还在努力开发3.5.x版本。


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