2016-07-10 4 views
1

Я создал класс Python с некоторыми атрибутами string/number и атрибутом списка. Теперь мне нужен список некоторых объектов этого класса без дубликатов. Объекты могут иметь одинаковые значения (равные), но ни один объект не должен присутствовать более одного раза.Python список изменяемых объектов без дубликатов

Я знаю, что устанавливает только поддерживающие неизменяемые объекты, но значения моих объектов будут меняться.

Есть ли другой подходящий тип данных для этой проблемы? С технической точки зрения, мне нужен массив ссылок на объекты без дубликатов, которые реализуют все методы коллекционного класса.

+0

Понятно, что это не имеет большого смысла - если вы измените один из ваших изменяемых объектов, вы можете изменить его, чтобы он стал идентичным чему-то еще в списке. Если вы выполняете одноразовую фильтрацию, вы можете рассмотреть подход «отпирания», преобразовывая все в неизменяемый тип, используя 'set()', а затем преобразовывая обратно в изменяемый тип. –

+0

Меня не интересует равенство. Объекты представляют объект в реальном мире. Объекты могут быть класса «человек» с атрибутом высоты. В списке может быть более одного человека с одинаковой высотой, но каждый человек может быть только один раз. – schoeberl

+0

Как следует из ответов на связанный вопрос, установите для работы из окна с пользовательскими классами, потому что функция по умолчанию __hash__ возвращает значение, основанное на идентификаторе объекта, которое не изменяется, если значения объекта изменяются. – schoeberl

ответ

0

set() работает точно так, как вы надеетесь. Просто используйте его напрямую:

class Person(object): 
    def __init__(self, height): 
     self.height = height 

Tom = Person(190) 
George = Person(200) 
Bob = Person(200) 

friends = set([Tom, George, Bob]) 
assert len(friends) == 3 
+0

Интересно, почему они сделали список «unhashable», в то время как он мог работать так же, как с пользовательскими классами. Я думаю, это решение не будет работать, если Person выведен из списка. – schoeberl

0

Я бы рекомендовал для цикла, таких как это:

unique = [] 
for item in yourList: 
    if not item in unique: 
     unique.append(item) 

Но, как для встроенных типов, наборы и dicts не хэш этих классов, как вы только что упомянули.

0

Если я правильно понял ваш вопрос, у вас есть изменяемый класс с оператором равенства, который проверяет некоторые из его изменяемых атрибутов, чтобы определить, равны ли два экземпляра. Вы хотите создать список этих экземпляров, исключая только повторяющиеся ссылки на один и тот же экземпляр, а не равные значения.

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

# given some pre-existing list of objects, initial_list 

seen_ids = set() 
deduped_list = [] 
for instance in initial_list: 
    if id(instance) not in seen_ids: 
     deduped_list.append(instance) 
     seen_ids.add(id(instance)) 

Вы можете вместо этого использовать словарь и выражение генератора, если вы хотите, чтобы сделать все это на одно выражение:

deduped_list = list(dict((id(instance), instance) for instance in initial_list).values()) 

list вызов необходим, только если вы используете Python 3 и нужен реальный объект списка. Если вам просто нужно что-то итеративное, возвращаемое значение от values будет работать как можно точнее. Если вам нужно, чтобы значения были в том же порядке, они сначала появились в исходном списке, вы можете использовать OrderedDict.

+0

Я предполагаю, что это решение, но управление адресами памяти (возвращаемое значение id()) с помощью python не похоже на очень эффективный способ. – schoeberl

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