Форум сайта python.su
Как в питоне 2.2 просто отсортировать по ключу?
В 2.4 и 2.5 делаю так: mass.sort(key=operator.attrgetter(“Date”))
а в 2.2 attrgetter функции нету (((. Или надо свою писать?
Офлайн
sorry. уже нашёл.
def sortby(somelist, n):
nlist = [(x, x) for x in somelist]
nlist.sort()
return
Офлайн
Свою написать несложно:
my_attrgetter = lambda attr: lambda obj, attr=attr: getattr(obj, attr)
lst =
get_count = my_attrgetter('count')
print get_count(lst)(3) # количество троек в lst
Если getter используется только один раз, функцию можно не именовать:
class s(object):
def __init__(self, s):
self.s = s
def __repr__(self):
return self.s
mass =
print mass
mass.sort(key=lambda obj: getattr(obj, “s”))
print mass
Но работать в версии ниже 2.4 не будет: раньше параметра key для sort не было. Однако вполне можно обойтись и без этого параметра:
mass =
mass.sort(cmp = lambda x, y: cmp(x.s, y.s))
print mass
Последний вариант будет работать значительно (возможно на порядки) быстрее и экономичнее по расходу памяти чем привденный тобой вариант с использованием временного списка.
Офлайн
спасибо за исчерпывающий ответ.
Офлайн
TmrЗдесь вот ой как не факт… key всегда экономичнее чем cmp, потому что функция вызывается многократно для каждого элемента а key только единожды, а вариант Cyxapeff'a больше соответствует подходу key (Кстати, это отражено в стандартной доке)
Но работать в версии ниже 2.4 не будет: раньше параметра key для sort не было. Однако вполне можно обойтись и без этого параметра:mass = [s('aaaa'), s('aa'), s('aaa'), s('aaaaa'), s('a')] mass.sort(cmp = lambda x, y: cmp(x.s, y.s)) print mass
Последний вариант будет работать значительно (возможно на порядки) быстрее и экономичнее по расходу памяти чем привденный тобой вариант с использованием временного списка.
Отредактировано (Март 16, 2007 21:04:24)
Офлайн
xonixНе совсем понял о чем речь… Функция, создаваемая функцией передаваемой как параметр key, тоже вызывается для каждого элемента, чтобы получить значение атрибута.
Здесь вот ой как не факт… key всегда экономичнее чем cmp, потому что функция вызывается многократно для каждого элемента а key только единожды, а вариант Cyxapeff'a больше соответствует подходу key (Кстати, это отражено в стандартной доке)
Отредактировано (Март 19, 2007 17:31:20)
Офлайн
В том то и дело, что key вызывается 1 раз для каждого элемента (т.е. сложность ~n*Сложность(key)). А функция cmp вызывается единожды для КАЖДОГО СРАВНЕНИЯ, коих будет ~n*n => сложность будет ~n*n*Сложность(cmp). Хотя тут я наврал слегка. n*n это при сортировке пузырьком, при быстрой сортировке и сортировке слиянием будет ~n*ln(n). Но все рано ассимптотика будет n против n * ln n в лучшем случае.
Офлайн
Посмотрел на теоретические споры, решил всё-таки проверить. Итак:
from time import time
from random import randint
N=1000
class s(object):
def __init__(self, s):
self.s = s
def __repr__(self):
return self.s
def sort1(somelist):
nlist =
nlist.sort()
return
def sort2(somelist):
somelist.sort(cmp = lambda x, y: cmp(x.s, y.s))
return somelist
list1=
for i in xrange(N):
list1.append(s(randint(0,1000000)))
list2=list1
time1=time()
sort1(list1)
print ‘Time sort1 = ’, time()-time1
time2=time()
sort2(list2)
print ‘Time sort2 = ’, time()-time2
Результаты:
N=1000
Time sort1 = 0.0
Time sort2 = 0.0160000324249
N=10000
Time sort1 = 0.0469999313354
Time sort2 = 0.156000137329
N=100000
Time sort1 = 0.93700003624
Time sort2 = 2.29699993134
N=1000000
Time sort1 = 530.907000065
Time sort2 = 243.906000137
Офлайн
Striver, спасибо за эксперимент!
xonixЭто действительно так, но поскольку внутри sort, очевидно, все равно вызыается cmp, то при использовании анонимной функции для вызова cmp, время работы sort увеличивется на <сложность sort> * (<время для передачи параметров функции и возвращения результата> + <время обращения к атрибутам объекта>). Для не очень больших величин этим можно пренебречь, но оказывается, к сожалению, не в Python…
В том то и дело, что key вызывается 1 раз для каждого элемента (т.е. сложность ~n*Сложность(key)). А функция cmp вызывается единожды для КАЖДОГО СРАВНЕНИЯ, коих будет ~n*n => сложность будет ~n*n*Сложность(cmp). Хотя тут я наврал слегка. n*n это при сортировке пузырьком, при быстрой сортировке и сортировке слиянием будет ~n*ln(n). Но все рано ассимптотика будет n против n * ln n в лучшем случае.
N = 1000
Time cmp = 4.64099979401
Time lambda: cmp = 10.0780000687
Ratio = 2.17151487093
N = 2000
Time cmp = 18.5780000687
Time lambda: cmp = 40.2029998302
Ratio = 2.1640111789
N = 4000
Time cmp = 73.625
Time lambda: cmp = 160.780999899
Ratio = 2.18378268114
N = 8000
Time cmp = 298.094000101
Time lambda: cmp = 655.421999931
Ratio = 2.19870913104
Офлайн
ясен пень, что с лямбдой медленнее.
ее лучше с функциями высокого порядка использовать.
Офлайн