2013-07-16 2 views
2

У меня есть список экземпляров объектов, которые я хочу сортировать/уникально в новом списке. Каждый объект реализует множество свойств, но три важных свойства: a, b и c. Все три свойства возвращают целочисленное значение: a и b отсортированы по низким ценам и c сортируются по высоким ценам.Сортированный/уникальный список экземпляров объектов из большего списка?

Пример списка:

>>> x 
>>> [<Foo object at 0x2b371b90>, <Foo object at 0x2b371f38>, <Foo object at 0x2b3719e0>, <Foo object at 0x2b376320>, <Foo object at 0x2b3765f0>] 


Если цикл I и напечатал значение a, b и c в кортеж для каждого объекта, они будут выглядеть следующим образом:

>>> for o in x: 
... print (o.a, o.b, o.c) 
... 
(2, 78342112, 9) 
(2, 78342117, 3) 
(2, 78342112, 10) 
(2, 78342112, 8) 
(2, 78342117, 4) 


Я выяснил, как сортировать список по a/b, будучи низким-высоким и c, будучи высоким-низким, определяя key() функции в классе объекта:

def key(self): 
    return (self.a, self.b, -self.c) 


И попутно, что в sorted():

x2 = sorted(x, key=lambda x:x.key()) 
>>> for o in x2: 
... print (o.a, o.b, o.c) 
... 
(2, 78342112, 10) 
(2, 78342112, 9) 
(2, 78342112, 8) 
(2, 78342117, 4) 
(2, 78342117, 3) 


Для этих конкретных объектов, уникальность между экземплярами зависит от того, если a и b являются один и тем же значением между двумя экземплярами , Если они разные, то c никогда не рассматривается, иначе мы предпочитаем наибольшее значение c. То, что я хотел бы сделать, это создать новый список из x или x2 в моих примерах выше, который содержит только один экземпляр для каждого случая, когда a и b совпадают, и сохранить тот, чье значение c является самым большим. Новый список, , будет выглядеть следующим образом:

>>> x3 = <magic sorting/unique function called here> 
>>> for o in x3: 
... print (o.a, o.b, o.c) 
... 
(2, 78342112, 10) 
(2, 78342117, 4) 


Я думаю, что я могу сделать это с помощью reduce() и пользовательскую функцию, но алгоритм/логика сделать так просто пни меня в данный момент.

Идеи?

+1

Более простое использование несвязанной функции 'key = ClassName.key' –

+0

@gnibbler: Не знал об этом подходе. Множество примеров, которые я вижу, просто используют 'lambda' и проверяют некоторое свойство объекта. Есть ли какие-либо предпосылки о том, как это работает? – Kumba

+0

Это просто более простой способ вызвать функцию 'key'. Помните, что 'Foo.key (foo)' совпадает с вызовом 'foo.key()'. Поскольку foo передается ключевой функции, вы можете оставить лямбда вне с помощью метода unbound вместо –

ответ

1

Один из способов сделать это с помощью itertools.groupby():

import itertools 

x3 = [next(g) for k, g in itertools.groupby(x2, lambda x:(x.a, x.b))] 

Это выбирает первый элемент каждой группы с тем же ключом.

+0

Я знаю, что я отметил этот python-2.7, но я тестирую внутри интерпретатора Python 2.4 на данный момент, в котором отсутствует 'next() '. Знать о реализации 'next()' for 2.4? – Kumba

+1

'next (g)' переводится в 'g.next()', если у вас нет функции 'next'. – user2357112

+0

@ user2357112: Спасибо за подсказку! – Kumba

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