298 votes

Comment filtrer un dictionnaire en fonction d'une fonction de condition arbitraire ?

J'ai un dictionnaire de points, par exemple :

>>> points={'a':(3,4), 'b':(1,2), 'c':(5,5), 'd':(3,3)}

Je veux créer un nouveau dictionnaire avec tous les points dont la valeur x et y est inférieure à 5, c'est-à-dire les points 'a', 'b' et 'd'.

Selon le le livre chaque dictionnaire a le items() qui renvoie une liste de (key, pair) tuple :

>>> points.items()
[('a', (3, 4)), ('c', (5, 5)), ('b', (1, 2)), ('d', (3, 3))]

J'ai donc écrit ceci :

>>> 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)}

Existe-t-il un moyen plus élégant ? Je m'attendais à ce que Python dispose d'un systÃ?me de gestion de l'équilibre entre les deux. dictionary.filter(f) fonction...

0 votes

559voto

Thomas Points 63635

Vous pouvez utiliser une dictée de compréhension :

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

Et dans Python 2, à partir de la version 2.7 :

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

21 votes

Upvote ! C'est plus de deux fois plus rapide que l'approche plus générale de Martellis. Notez que vous pouvez aussi utiliser des vues (comme iteitems, elles ne sont PAS une copie du dict items) : {k : v for k, v in points.viewitems() if v[0] < 5 and v[1] < 5}

8 votes

Et voici une bonne explication de la raison pour laquelle l'appel de fonction dict() est plus lent que la syntaxe constructeur/littéral {}. doughellmann.com/2012/11/

1 votes

Gardez à l'esprit que iteritems a été supprimé dans Python 3. Mais vous pouvez utiliser items à la place. Il se comporte de la manière suivante iteritems fonctionne dans les anciennes versions.

119voto

Alex Martelli Points 330805
dict((k, v) for k, v in points.items() if all(x < 5 for x in v))

Vous pouvez choisir d'appeler .iteritems() au lieu de .items() si vous êtes en Python 2 et en points peut avoir un lot d'entrées.

all(x < 5 for x in v) peut s'avérer inutile si vous êtes certain que chaque point sera toujours uniquement en 2D (dans ce cas, vous pourriez exprimer la même contrainte avec une option and ) mais cela fonctionnera très bien;-).

27voto

sizzzzlerz Points 2000
points_small = dict(filter(lambda (a,(b,c)): b<5 and c < 5, points.items()))

1 votes

En Python 2, utilisez iteritems() au lieu de items().

6 votes

En python 3.5, ceci renvoie une erreur : points_small = dict(filter(lambda (a,(b,c)) : b<5 and c < 5, points.items())) ^ SyntaxError : invalid syntax `.

2 votes

Je pense que ce n'est pas supporté par python 3.

10voto

nosklo Points 75862
dict((k, v) for (k, v) in points.iteritems() if v[0] < 5 and v[1] < 5)

6voto

dict((k, v) for (k, v) in points.iteritems() if v[0] < 5 and v[1] < 5)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X