4 votes

Utiliser des dicts comme éléments d'un ensemble en Python

Existe-t-il un moyen de placer des objets dict dans un ensemble en Python en utilisant une méthode simple, comme une fonction comparateur ?

J'ai trouvé quelques solutions ici qui impliquaient un tas de choses qui semblaient vraiment complexes et sujettes à erreur (il semblait y avoir des problèmes avec l'itération sur le dict dans des ordres indéfinis, etc...). Ce serait bien de faire quelque chose comme ça, qui n'est techniquement pas valide mathématiquement parce que deux objets peuvent avoir des informations différentes, mais être évalués comme égaux, mais qui fonctionne très bien pour de nombreux cas d'utilisation dans la vie réelle :

# One of the dicts:
widget = {
     lunch:  'eggs',
     dunner: 'steak'
}

# Define a comparator function (ignores dinner)
def comparator(widget1, widget2):
     return widget1['lunch'] > widget2['lunch']

widget_set = set([widget], comparator)

6voto

Martijn Pieters Points 271458

Non, vous ne pouvez pas. Vous ne pouvez placer que des valeurs immuables dans un ensemble. Cette restriction ne se limite pas à la possibilité de comparer des valeurs ; vous devez tester l'égalité et être en mesure d'obtenir une valeur de hachage, et surtout la valeur a de rester stable. Les valeurs mutables ne satisfont pas à cette dernière exigence.

Un dictionnaire peut être rendu immuable en le transformant en une série de tuples clé-valeur ; à condition que les valeurs soient également immuables, ce qui suit fonctionne :

widget_set = {tuple(sorted(widget.items()))}  # {..} is a set literal, Python 2.7 and newer

Il est ainsi possible de vérifier la présence du même dictionnaire en testant la présence de tuple(sorted(somedict.items())) in widget_set au moins. En transformant les valeurs en dict il s'agit d'appeler dict sur celui-ci :

dict(widget_set.pop())

Démonstration :

>>> widget = {
...      'lunch':  'eggs',
...      'dunner': 'steak'
... }
>>> widget_set = {tuple(sorted(widget.items()))}
>>> tuple(sorted(widget.items())) in widget_set
True
>>> dict(widget_set.pop())
{'lunch': 'eggs', 'dunner': 'steak'}

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