Подтвердить что ты не робот

Как получить доступ к элементу набора с использованием эквивалентного объекта?

Если у меня есть объект, который сравнивается с элементом набора 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, который отображает каждую клавишу для себя, а не для набора.

4b9b3361

Ответ 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 заключается в создании пользовательского словарного класса, который имеет набор как один из его членов, реализует прокси-механизмы для набор элементов, а также в словарных и установочных методах синхронизирует как словарь, так и заданное содержимое. Это займет много времени, чтобы реализовать право, но относительно просто.