Как получить доступ к элементу набора, используя эквивалентный объект?
Если у меня есть объект, который сравнивается равным элементу набора 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
, РЕДАКТИРОВАТЬ: Это не работает, когда 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, который отображает каждый ключ на себя, а не на набор.
2 ответа
Я нашел похожий вопрос в списке python: получить элемент из набора. Есть умный ответ со ссылкой на get_equivalent(контейнер, элемент) (рецепт Python).
Хитрость заключается в том, чтобы создать объект-обертку для объекта "ключ" и проверить, находится ли обертка в наборе, используя in
оператор. Если хэши оболочки равны ключу, его __eq__
Метод может получить доступ к объекту в наборе и сохранить ссылку на него. Важным моментом обсуждения является то, что __eq__
метод из набора элементов должен возвращать NotImplemented
для нераспознанных типов, в противном случае __eq__
может не позвонить.
Ваш вариант использования звучит так, как будто это вариант использования словарей. Используйте в качестве ключей атрибут объекта, который сравнивается равным "чужому" объекту, и в качестве значений самих нужных объектов.
Если это простой вариант использования, и вы можете иметь линейный поиск, вы можете сделать очевидное - это было бы неплохо:
def get_equal(in_set, in_element):
for element in in_set:
if element == in_element:
return element
return None
Если вам нужно именно то, о чем вы просите (я могу удивиться, некоторые варианты использования для этого) - вам нужно создать собственный класс словаря, в котором набор является одним из его членов, реализуйте прокси-методы для набора элементов. и как в словаре, так и в методах set, поддерживает синхронизацию словаря и заданного содержимого. Это может занять много времени для реализации правильно, но относительно просто.