J'ai un dictionnaire de points, disons:
>>> points={'a':(3,4), 'b':(1,2), 'c':(5,5), 'd':(3,3)}
Je souhaite créer un nouveau dictionnaire avec tous les points dont les valeurs x et y sont inférieures à 5, c’est-à-dire les points "a", "b" et "d".
Selon le le livre , chaque dictionnaire possède la fonction items()
, qui renvoie la liste de (key, pair)
Tuple:
>>> points.items()
[('a', (3, 4)), ('c', (5, 5)), ('b', (1, 2)), ('d', (3, 3))]
Alors j'ai é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)}
Y a-t-il un moyen plus élégant? Je m'attendais à ce que Python ait une fonction super-géniale dictionary.filter(f)
...
De nos jours, dans Python 2.7 et versions ultérieures, vous pouvez utiliser une compréhension dictée:
{k: v for k, v in points.iteritems() if v[0] < 5 and v[1] < 5}
Et en Python 3:
{k: v for k, v in points.items() if v[0] < 5 and v[1] < 5}
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 dans Python 2 et points
pouvez avoir un lot d'entrées.
all(x < 5 for x in v)
peut être exagéré si vous savez avec certitude que chaque point sera toujours en 2D uniquement (dans ce cas, vous pourriez exprimer la même contrainte avec un and
), mais cela fonctionnera correctement ;-).
points_small = dict(filter(lambda (a,(b,c)): b<5 and c < 5, points.items()))
>>> 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)}
dict((k, v) for (k, v) in points.iteritems() if v[0] < 5 and v[1] < 5)
Je pense que la réponse d'Alex Martelli est certainement la manière la plus élégante de le faire, mais je voulais juste ajouter un moyen de satisfaire votre besoin pour une méthode super géniale dictionary.filter(f)
dans une sorte de méthode pythonique:
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)
Fondamentalement, nous créons une classe qui hérite de dict
, mais ajoute la méthode de filtrage. Nous avons besoin d'utiliser .items()
pour le filtrage, car utiliser .iteritems()
lors d'une itération destructive soulève une exception.
dict((k, v) for (k, v) in points.iteritems() if v[0] < 5 and v[1] < 5)