如何根据任意条件函数过滤字典?

Ada*_*tan 190 python dictionary filter

我有点词典,说:

>>> points={'a':(3,4), 'b':(1,2), 'c':(5,5), 'd':(3,3)}
Run Code Online (Sandbox Code Playgroud)

我想创建一个新的字典,其中包含x和y值小于5的所有点,即点'a','b'和'd'.

根据该书,每个字典都有items()函数,它返回一个(key, pair) 元组列表:

>>> points.items()
[('a', (3, 4)), ('c', (5, 5)), ('b', (1, 2)), ('d', (3, 3))]
Run Code Online (Sandbox Code Playgroud)

所以我写了这个:

>>> for item in [i for i in points.items() if i[1][0]<5 and i[1][1]<5]:
...     points_small[item[0]]=item[1]
...
>>> points_small
{'a': (3, 4), 'b': (1, 2), 'd': (3, 3)}
Run Code Online (Sandbox Code Playgroud)

有更优雅的方式吗?我期待Python有一些超级棒的dictionary.filter(f)功能......

Tho*_*mas 391

如今,在Python 2.7及更高版本中,您可以使用dict理解:

{k: v for k, v in points.iteritems() if v[0] < 5 and v[1] < 5}
Run Code Online (Sandbox Code Playgroud)

在Python 3中:

{k: v for k, v in points.items() if v[0] < 5 and v[1] < 5}
Run Code Online (Sandbox Code Playgroud)

  • 给予好评!这比Martellis更通用的方法快两倍多.请注意,您也可以使用视图(如iteitems,它们不是dict项的副本):{k:v for k,v in points.viewitems()如果v [0] <5且v [1] < 5} (14认同)
  • 这里有一个很好的解释为什么函数调用dict()比构造函数/文字语法慢{} http://doughellmann.com/2012/11/the-performance-impact-of-using-dict-instead-of -in-CPython的,2-7-2.html (5认同)

Ale*_*lli 108

dict((k, v) for k, v in points.items() if all(x < 5 for x in v))
Run Code Online (Sandbox Code Playgroud)

您可以选择调用.iteritems()而不是.items()如果您使用的是Python 2并且points可能有很多条目.

all(x < 5 for x in v)如果你确定每个点总是只有2D(在这种情况下你可能用a表示相同的约束and)但是它可以正常工作;-).可能有点矫枉过正.


siz*_*erz 20

points_small = dict(filter(lambda (a,(b,c)): b<5 and c < 5, points.items()))
Run Code Online (Sandbox Code Playgroud)

  • 在python 3.5中,这会返回一个错误:points_small = dict(filter(lambda(a,(b,c)):b <5和c <5,points.items()))^ SyntaxError:语法无效` (2认同)
  • 我认为 python 3 不支持它 (2认同)

小智 14

>>> points = {'a': (3, 4), 'c': (5, 5), 'b': (1, 2), 'd': (3, 3)}
>>> dict(filter(lambda x: (x[1][0], x[1][1]) < (5, 5), points.items()))

{'a': (3, 4), 'b': (1, 2), 'd': (3, 3)}
Run Code Online (Sandbox Code Playgroud)

  • 太好了!值得一提的是,这是Py3,因为lambda无法再解压缩元组参数(请参阅[PEP 3113](https://www.python.org/dev/peps/pep-3113/)) (2认同)

nos*_*klo 9

dict((k, v) for (k, v) in points.iteritems() if v[0] < 5 and v[1] < 5)
Run Code Online (Sandbox Code Playgroud)


qww*_*wwq 7

我认为,亚历克斯·马尔泰利的答案肯定是最优雅的方式来做到这一点,但只是想补充的方式来满足你渴望得到一个超级真棒dictionary.filter(f)在Python化的方式排序方法:

class FilterDict(dict):
    def __init__(self, input_dict):
        for key, value in input_dict.iteritems():
            self[key] = value
    def filter(self, criteria):
        for key, value in self.items():
            if (criteria(value)):
                self.pop(key)

my_dict = FilterDict( {'a':(3,4), 'b':(1,2), 'c':(5,5), 'd':(3,3)} )
my_dict.filter(lambda x: x[0] < 5 and x[1] < 5)
Run Code Online (Sandbox Code Playgroud)

基本上我们创建了一个继承自的类dict,但添加了filter方法.我们确实需要.items()用于过滤,因为.iteritems()在破坏性迭代时使用会引发异常.


Ign*_*ams 6

dict((k, v) for (k, v) in points.iteritems() if v[0] < 5 and v[1] < 5)
Run Code Online (Sandbox Code Playgroud)