Является ли определение вашего хеша таким способом, имеет ли смысл для вашего приложения, решать вам, но это кажется маловероятным.
В любом случае, я могу представить два варианта, которые будут «такими же быстрыми, как» набором - O (1) вместо O (n) - и их скорость зависит от реализации хэш-функции, как вы описываете:
Во-первых, сведи свой класс и создай экземпляры:
class Item():
def __init__(self, a, b):
self.a = a
self.b = b
def __hash__(self):
return hash(self.a)
def __eq__(self,other):
if isinstance(other, self.__class__):
# Ignoring .b attribute
return self.a == other.a
else:
return NotImplemented
def __repr__(self):
return "Item(%s, %s)" % (self.a, self.b)
i1 = Item(1,2)
i2 = Item(3,4)
i3 = Item(1,5)
print(i1 == i2) # False (.a's don't match)
print(i1 == i3) # True (.a's match)
Метод 1: значения dict
# Using a dict
updating_set = {}
updating_set[i1] = i1 # .values(): [Item(1, 2)]
updating_set[i2] = i2 # .values(): [Item(1, 2), Item(3, 4)]
updating_set[i3] = i3 # .values(): [Item(1, 5), Item(3, 4)]
print(list(updating_set.values()))
# [Item(1, 5), Item(3, 4)]
Способ 2. Использование подкласса набора
# Using a set subclass
class UpdatingSet(set):
def add(self, item):
if item in self: super().remove(item)
super().add(item)
uset = UpdatingSet()
uset.add(i1) # UpdatingSet({Item(1, 2)})
uset.add(i2) # UpdatingSet({Item(1, 2), Item(3, 4)})
uset.add(i3) # UpdatingSet({Item(1, 5), Item(3, 4)})
Бонусный метод 3: Не требует специальной хэш-функции
class NewItem():
def __init__(self, a, b):
self.a = a
self.b = b
def __repr__(self):
return "Item(%s, %s)" % (self.a, self.b)
class ItemSet():
def __init__(self):
self.items = {}
def add(self, item):
item_hash = item.a
self.items[item_hash] = item
def values(self):
return self.items.values()
i1 = NewItem(1,2)
i2 = NewItem(3,4)
i3 = NewItem(1,5)
iset = ItemSet()
iset.add(i1) # .values(): [Item(1, 2)]
iset.add(i2) # .values(): [Item(1, 2), Item(3, 4)]
iset.add(i3) # .values(): [Item(1, 5), Item(3, 4)]
print(list(iset.values())) # [Item(1, 5), Item(3, 4)]
Этот третий подход не требует от вас реализации хеша (который может вызвать неожиданные побочные эффекты, но имитирует процесс хеширования внутри ItemSet.add()
, используя «хэш-функцию» в качестве ключа словаря.
Это, вероятно, ваша лучшая ставка, если вы действительно не хотите внедрить хэш и не знаете, каковы последствия этого решения.