Use dicts as items in a set in Python

人走茶凉 提交于 2019-12-12 11:50:24

问题


Is there a way to put some dict objects into a set in Python by using a simple method, like a comparator function?

Came across a few solutions on here that involved a bunch of stuff that looked really complex and error-prone (seemed to be problems with iterating over the dict in undefined orders, etc...). Would be nice to do something like this which is technically not mathematically valid because two objects can have different information, but be evaluated as equal, but works great for plenty of real life use cases:

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

回答1:


No, you cannot. You can only put immutable values into a set. This restriction has to do with more than just being able to compare values; you need to test both for equality and be able to obtain a hash value, and most of all the value has to remain stable. Mutable values fail that last requirement.

A dictionary can be made immutable by turning it into a series of key-value tuples; provided the values are immutable too, the following works:

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

This makes it possible to test for the presence of the same dictionary by testing for tuple(sorted(somedict.items())) in widget_set at least. Turning the values back into a dict is a question of calling dict on it:

dict(widget_set.pop())

Demo:

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


来源:https://stackoverflow.com/questions/16531382/use-dicts-as-items-in-a-set-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!