2012-05-31 3 views
3

Рассмотрим словарь с ключами создается с использованием объектов ниже класса:Запрашивание словарь ключ Python с пользовательскими объектами

class Point(object): 

    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

    def __eq__(self, other): 
     return self.x == other.x 

    def __hash__(self): 
     return self.x.__hash__() 

    def __ne__(self, other): 
     return self.x != other.x 

>>> a = Point(1,1) 
>>> b = Point(0, 2) 
>>> dct = {} 
>>> dct[a] = 15 
>>> dct[b] = 16 
>>> dct[a] 
15 
>>> c = Point(1,None) 
>>> dct[c] 
15 

Это происходит потому, что c и a доля тот же хэш и равны. Есть ли O (1) способ реализации функции, заданной c возвращает a (как по отношению к О (п) реализации ниже):

def getKey(dct, key): 
    for k in dct: 
     if k == key: 
      return k 
    return None 
+2

Вы определили, что ваши объекты Point равны тогда и только тогда, когда их значения x равны.Есть ли какая-то причина, по которой вы не хотите, чтобы значение y фигурировало в вещах? –

+2

То, что вы ищете, не существует, но вы можете создать его путем подкласса 'dict' и поддержания внутреннего словаря, который отображает ключи для себя. Это добавило бы некоторые накладные расходы для каждой модификации словаря, но вы могли бы получить фактический ключевой объект в O (1) через внутренний словарь. –

+0

Я надеялся, что смогу сделать это аккуратным питоническим способом. Спасибо F.J. за указание на отсутствие тривиального способа сделать это. – GeneralBecos

ответ

2

Ваша функция всегда возвращает None или ключ, так Я не понимаю вашу точку ...

по сложности, предположим, что вам потребуется, по крайней мере O (журнал (п)), , например, если DCT как я полагаю, словарь, так что о:

def getKey(dct, key): 
    if dct.has_key(key): 
     return key 
    return None 

и если вы хотите, чтобы вернуть это значение, так что просто использовать: dct.get (ключ, None)

+3

Это не то же самое, 'getKey (dct, c)' будет возвращать 'a' в код OP и' c' в вашем коде. –

+0

Действительно - я забыл о переопределенной функции '__eq__'. Итак, как насчет добавления нового словаря: 'keyMap [x] = KeyPoint' (где KeyPoint - это точка (x, y), которая является ключом в' dict' – ddzialak

+0

@ddzialak: Вниз ответ (не отвечает на вопрос). – GeneralBecos

1

Вы можете, вероятно, сделать значения для словаря в качестве кортежей или списков, состоящих из ключа и само значение , используя свой пример:

>>> a = Point(1,1) 
>>> b = Point(0, 2) 
>>> dct = {} 
>>> dct[a] = (15, a) 
>>> dct[b] = (16, b) 
>>> dct[a] 
(15, <Point object at 0xb769dc2c>) 
>>> c = Point(1,None) 
>>> dct[c] 
(15, <Point object at 0xb769dc2c>) 

теперь вы можете получить a используя c так:

>>> dct[c][1] 
0

Другими словами, данный список объектов и объект X, найти элемент в списке, который имеет то же хэш-значение, как X. Рассмотрим:

class A(object): 
    def __init__(self, x, blah): 
     self.x = x 
     self.blah = blah 
    def __eq__(self, other): 
     return self.x == other.x 
    def __hash__(self): 
     return self.x 
    def __repr__(self): 
     return '%d-%s' % (self.x, self.blah) 


ls = [A(1, 'one'), A(2, 'FOO'), A(3, 'three')] 
test = A(2, 'BAR') 
print test, '=', (set(ls) - (set(ls) - set([test]))).pop() 

Для работы с словаря, например, заменить set(ls) с viewkeys:

dct = dict(zip(ls, range(100))) 
print test, '=', (dct.viewkeys() - (dct.viewkeys() - set([test]))).pop() 
+0

Это O (n) так же, как версия в вопросе.Он хотел, чтобы решение по постоянному времени, например, FJ, Karl и Amr предложили. – agf

+0

Чтобы добавить немного больше цветов: Создание самих наборов будет линейным временем + вычитание будет линейным, что сделает это хуже, чем решение, описанное в заявлении проблемы. – GeneralBecos

+0

@GeneralBecos: добро пожаловать;) – georg

1

Это происходит потому, что с и одни и те же хэш.

Нет; это происходит потому, что они разделяют хэш и сравнивают друг с другом.

В общем случае неравные объекты могут иметь значение хэша одинакового значения. (Равные объекты должен хэш с тем же значением.)

Ваш __eq__ определяет объекты как равные, если они имеют одинаковую координату x. Это явно неправильно; они должны быть равны, если обе координаты равны.

Но похоже, что это не то, что вы действительно пытаетесь сделать. Если вы хотите «дать c, получите a», то то, что вы действительно просите, это найти, учитывая точку, все остальные точки с одинаковой координатой x.

Это просто: сделайте привязку к координатам x-координат для точек с координатами.

+0

Меня больше интересует общая концепция. Не имеет особого отношения к точке. Я просто использовал Point в качестве примера. Спасибо, что указали ошибку в моей постановке проблемы. Фиксация. – GeneralBecos

Смежные вопросы