Как получить доступ к элементу набора с использованием эквивалентного объекта?
Если у меня есть объект, который сравнивается с элементом набора Python, но не является тем же самым объектом, существует ли разумный способ получить ссылку на объект в наборе? Вариант использования будет использовать набор для идентификации и совместного использования дублированных данных.
Пример (Python 2.7):
>>> a = "This is a string"
>>> b = "This is a string"
>>> a is b
False
>>> a == b
True
>>> s = set((a,))
>>> b in s
True
Как получить ссылку на a
с помощью b
и s
? Я могу думать об одном способе, но я не уверен, что это не зависит от реализации, получаете ли вы a
или b
. EDIT: Это не работает, когда s имеет более одного элемента; пересечение вполне естественно реализовано примерно как [x for x in smaller_set if x in larger_set]
>>> for x in set((b,)).intersection(s): c = x
...
>>> c is a
True
Возможно, хорошим решением будет использование dict, который отображает каждую клавишу для себя, а не для набора.
Ответы
Ответ 1
Я нашел аналогичный вопрос в python-списке: Получить элемент из набора. Существует умный ответ со ссылкой на get_equivalent (контейнер, элемент) (рецепт Python).
Хитрость заключается в том, чтобы создать объект-оболочку для объекта "ключ" и проверить, находится ли оболочка в наборе с помощью оператора in
. Если хэширование оболочки равно ключу, его метод __eq__
может получить доступ к объекту в наборе и сохранить ссылку на него. Важным моментом в обсуждении является то, что метод __eq__
заданных элементов должен возвращать NotImplemented
для непризнанных типов, иначе оболочка __eq__
не может быть вызвана.
Ответ 2
Ваш случай использования звучит так, как будто он используется для словарей. Используйте в качестве ключей атрибут объекта, который сравнивается с "чужим" объектом, а также как значения самих желаемых объектов.
Если это простой случай использования, и вы можете иметь линейный seartch, однако, вы могли бы сделать очевидное - это было бы неплохо:
def get_equal(in_set, in_element):
for element in in_set:
if element == in_element:
return element
return None
Если вам нужно то, что именно вы запрашиваете (я могу задаться вопросом о некоторых случаях использования) - wya to go заключается в создании пользовательского словарного класса, который имеет набор как один из его членов, реализует прокси-механизмы для набор элементов, а также в словарных и установочных методах синхронизирует как словарь, так и заданное содержимое. Это займет много времени, чтобы реализовать право, но относительно просто.