2010-08-17 5 views
2

У меня есть два экземпляра объекта в спискеКаков наилучший способ сортировки элементов на один из элементов значения

class Thing(): 
    timeTo = 0 
    timeFrom = 0 
    name = "" 

o1 = Thing() 
o1.name = "One" 
o1.timeFrom = 2 

o2 = Thing() 
o2.timeTo = 20 
o2.name = "Two" 

myList = [o1, o2] 


biggestIndex = (myList[0].timeFrom < myList[1].timeTo) & 1 
bigger = myList.pop(biggestIndex) 
lesser = myList.pop() 

print bigger.name 
print lesser.name 

как o1 и o2 имеют два свойства, которые я хочу, чтобы сравнить первый в перечисляет timeFrom свойство и второе timeTo свойство eachother.

Я чувствую, что это немного неудобно и странно, возможно ли, что это лучший и читаемый подход?

ответ

2

Лучшее решение сделать Thing экземпляры сортировкой. Вы можете сделать это путем реализации __lt__:

class Thing(): 
    timeTo = 0 
    timeFrom = 0 
    name = "" 

    def __lt__(self, other): 
     return self.timeFrom < other.timeTo 


lesser, bigger = sorted(myList) 

python2 имеет lesser, bigger = sorted(myList, cmp=lambda one,other: one.timeFrom < other.timeTo).

В Python3 cmp ушел, я думаю, заставить людей делать (или учиться) ООП и писать адаптер .

class SortAdaper(object): 
    def __init__(self, obj): 
     self.obj = obj 

class TimeLineSorter(SortAdaper): 
    """ sorts in a timeline """ 
    def __lt__(self, other): 
     return self.obj.timeFrom < other.obj.timeTo 

class NameSorter(SortAdaper): 
    """ sorts by name """ 
    def __lt__(self, other): 
     return self.obj.name < other.obj.name 

print sorted(myList, key=TimeLineSorter) 
print sorted(myList, key=NameSorter) 
+0

@Justin Ardini: Это свойство метрики, определенной OP. o1 и o2 просто не сортируются в этом случае. –

+0

Если у вас есть 'o1.timeFrom> = o2.timeTo' и' o2.timeFrom> = o1.timeTo', и вы хотите, чтобы это 'o1.timeFrom <= o1.timeTo' (что очень разумно, учитывая имена переменных) это означает (сделайте математику!), что 'o2.timeFrom> = o2.timeTo' ... и это не имеет смысла! –

+0

Отлично! Я закончил писать сортировщик и использовал его в качестве ключевого аргумента для сортированной функции, спасибо! – Joelbitar

1

см attrgetter

import operator 

getter = operator.attrgetter('timeFrom') 

bigger = max(myList, key=getter) 
lesser = min(myList, key=getter) 

print bigger.name 
print lesser.name 

EDIT:

attrgetter также wokrs с отсортирован или везде, где ключ функция необходима.

lesser, bigger = sorted(myList, key=getter) 
+0

+1, 'operator.attrgetter', безусловно, правильный подход (но ** пожалуйста ** редактировать это A, чтобы сделать это правильно: начните с 'import operator' и используйте' operator.attrgetter' явно - иначе будет не только дискуссионный стиль, но и _sure_, чтобы оставить новичков ужасно озадаченными, поскольку Python дает им ошибку «name not found»! !!). –

+0

OP хочет сортировать, сравнивая * два атрибута *, поэтому это не может работать (и это не дает правильного результата). –

+0

как THC4k сказал, мне нужно сравнить один атрибут с другим атрибутом, есть ли способ, чтобы это соответствовало моей потребности в сравнении одного аттрибута с другим? – Joelbitar

0

Я хотел бы сделать это, если объект может иметь только одно из значений времени:

class Thing(object): 
    def __init__(self, name, time = 0, timename = 'to'): 
     self.name, self.time, self.timename = (name,time,timename) 

    def __repr__(self): 
     return "Thing(%r, %i, %r)" % (self.name, self.time, self.timename) 

    def __lt__(self, other): 
     return self.time < other.time 

o1 = Thing("One", 5, 'from') 

o2 = Thing("Two", 20, 'to') 

myList = [o1, o2] 

print myList 
print max(myList) 
print min(myList) 
Смежные вопросы