Уведомления

Группа в Telegram: @pythonsu

#1 Сен. 6, 2012 16:35:16

EBFE
Зарегистрирован: 2012-07-03
Сообщения: 99
Репутация: +  20  -
Профиль   Отправить e-mail  

Сортировка списка

PooH
Чем он им помешал то?!
Ну вроде бы тем, что “пересекался” с lt, le, eq, ne, gt, ge.
FishHook
а чем, собственно, вариант с лямбдой хуже или лучше варианта с itemgetter
В CPython itemgetter реализован на Cи
Pysrc/Modules/operator.c:325:/* itemgetter object
соответственно скорость выполнения выше.

import timeit
from operator import itemgetter
def bench_lambda_key(buf):
    return sorted(buf, key=lambda x: (x[2],x[1],x[0]))
def bench_lambda_auto_key(buf):
    return sorted(buf, key=lambda x: reversed(x))
def bench_itemgetter(buf):
    return sorted(buf, key=itemgetter(2,1,0))
def bench_keyfunc(buf):
    def keyfunc(x):
        return x[2],x[1],x[0]
    return sorted(buf, key=keyfunc)
def measure(func, arg, times):
    print " %s %s" % (func.__name__, timeit.timeit(lambda: func(arg),
                         number=times))
buffs = [[(i,i,i) for i in range(val,0,-1)]
         for val in (1000, 10000, 100000, 10000000)]
print [(buf[0],buf[-1]) for buf in buffs]
funcs = [func for name,func in globals().items() if name.startswith('bench_')] + [sorted]
for buf in buffs:
    assert buf[-1] < buf[0]
    assert buf[-1] == (1,1,1)
    print "Buflen:", len(buf)
    for func in funcs:       
        measure(func, buf, 3)
Python 2.7.3 (64-bit)
[((1000, 1000, 1000), (1, 1, 1)), ((10000, 10000, 10000), (1, 1, 1)), ((100000,
100000, 100000), (1, 1, 1)), ((10000000, 10000000, 10000000), (1, 1, 1))]
Buflen: 1000
 bench_itemgetter 0.00191706278265
 bench_keyfunc 0.00287790388817
 bench_lambda_key 0.00287559417398
 bench_lambda_auto_key 0.00300378331185
 sorted 0.000578968358455
Buflen: 10000
 bench_itemgetter 0.0194231565786
 bench_keyfunc 0.0218749181976
 bench_lambda_key 0.0152325651224
 bench_lambda_auto_key 0.0141616276402
 sorted 0.00305036254814
Buflen: 100000
 bench_itemgetter 0.130403383885
 bench_keyfunc 0.179477496455
 bench_lambda_key 0.178710286389
 bench_lambda_auto_key 0.152915013296
 sorted 0.040913892315
Buflen: 10000000
 bench_itemgetter 14.2914632193
 bench_keyfunc 19.6054661696
 bench_lambda_key 19.6240705325
 bench_lambda_auto_key 17.0308593215
 sorted 4.21384796845
pypy 1.9.0 (32-bit)
Buflen: 1000
 bench_itemgetter 0.0267988439111
 bench_keyfunc 0.00317316235289
 bench_lambda_key 0.00303457950113
 bench_lambda_auto_key 0.00624893175718
 sorted 0.000451934077677
Buflen: 10000
 bench_itemgetter 0.0240387354469
 bench_keyfunc 0.0165294696434
 bench_lambda_key 0.0145931592425
 bench_lambda_auto_key 0.0314840991576
 sorted 0.00325438730212
Buflen: 100000
 bench_itemgetter 0.298087864608
 bench_keyfunc 0.200838888196
 bench_lambda_key 0.201263105703
 bench_lambda_auto_key 0.219333539668
 sorted 0.0355272538576
Buflen: 10000000
 bench_itemgetter 48.9225983977
 bench_keyfunc 30.2210835331
 bench_lambda_key 29.9068399876
 bench_lambda_auto_key 30.5330650985
 sorted 4.42660690666

Отредактировано EBFE (Сен. 6, 2012 17:03:42)

Офлайн

#2 Сен. 6, 2012 20:25:56

odnochlen
Зарегистрирован: 2012-06-28
Сообщения: 794
Репутация: +  14  -
Профиль   Отправить e-mail  

Сортировка списка

Однако, просто sorted в 3 с лишним раза быстрее.

Офлайн

#3 Сен. 6, 2012 22:48:33

EBFE
Зарегистрирован: 2012-07-03
Сообщения: 99
Репутация: +  20  -
Профиль   Отправить e-mail  

Сортировка списка

Ну и для любителей черезмерной оптимизации и LINQ

class LinqMixin(object):
    def OrderBy(self, arg, reverse=False):
        if isinstance(arg, int):
            arg = itemgetter(arg)
        elif isinstance(arg, str):
            arg = attrgetter(arg)
        # else lambda expression
        self.sort(key=arg, reverse=reverse)
        return self
    def OrderByDescending(self, arg):
        return self.OrderBy(arg, True)
    ThenBy = OrderBy
    ThenByDescending = OrderByDescending
class CoolList(list, LinqMixin): pass
def bench_linq(buf):
    l_buf = CoolList(buf)
    return l_buf.OrderBy(2).ThenBy(1).ThenBy(0)
def bench_multiple_sort(buf):
    return sorted(sorted(sorted(buf, key=itemgetter(2)), key=itemgetter(1)), key=itemgetter(0))
Python 2.7.3 (64-bit)
 
Buflen: 100000
bench_linq 0.184998098335
bench_itemgetter 0.139423202773
bench_multiple_sort 0.197778516886
bench_lambda_auto_key 0.159128144483
bench_keyfunc 0.184526146735
bench_lambda_key 0.186749246648
sorted 0.0414897810546
Buflen: 10000000
bench_linq 19.0146251103
bench_itemgetter 14.8408456788
bench_multiple_sort 21.1929246525
bench_lambda_auto_key 17.6037073223
bench_keyfunc 20.4276331897
bench_lambda_key 20.6035298592
sorted 4.18729972853

Отредактировано EBFE (Сен. 6, 2012 23:34:03)

Офлайн

#4 Сен. 7, 2012 00:50:55

odnochlen
Зарегистрирован: 2012-06-28
Сообщения: 794
Репутация: +  14  -
Профиль   Отправить e-mail  

Сортировка списка

EBFE
черезмерной оптимизации
Что это? Это такое матное слово для питонистов?

OrderBy(2) - это не linq. Там аттрибуты указываются.

Офлайн

#5 Сен. 7, 2012 02:33:28

EBFE
Зарегистрирован: 2012-07-03
Сообщения: 99
Репутация: +  20  -
Профиль   Отправить e-mail  

Сортировка списка

odnochlen
OrderBy(2) - это не linq. Там аттрибуты указываются.
То есть LINQ не такой продвинутый? Ничего, бывает. На жабе вообще похожего нет
from collections import namedtuple
#
Person=namedtuple('Person', 'name age city')
#
b1 = CoolList([Person("Alice",21,"Redmond"),Person("Bob",20,"Boston"),
Person("Nadine",21,"Denver")])
#
>>> b1.OrderBy('age').ThenBy(lambda person: person.name)
[Person(name='Alice', age=21, city='Redmond'), Person(name='Bob', age=20, city='
Boston'), Person(name='Nadine', age=21, city='Denver')]
>>> b1.OrderBy('age').ThenBy(2)
[Person(name='Bob', age=20, city='Boston'), Person(name='Nadine', age=21, city='
Denver'), Person(name='Alice', age=21, city='Redmond')]
>>> b1.OrderBy(1).ThenBy(lambda person: person.name)
[Person(name='Alice', age=21, city='Redmond'), Person(name='Bob', age=20, city='
Boston'), Person(name='Nadine', age=21, city='Denver')]
>>> b1.OrderBy(lambda p: p.age).ThenBy('city')
[Person(name='Bob', age=20, city='Boston'), Person(name='Nadine', age=21, city='
Denver'), Person(name='Alice', age=21, city='Redmond')]

Отредактировано EBFE (Сен. 7, 2012 02:50:17)

Офлайн

#6 Сен. 7, 2012 08:44:13

odnochlen
Зарегистрирован: 2012-06-28
Сообщения: 794
Репутация: +  14  -
Профиль   Отправить e-mail  

Сортировка списка

EBFE
То есть LINQ не такой продвинутый? Ничего, бывает. На жабе вообще похожего нет
Просто на статических языках кортежи не есть гуд. Это питонистам по барабану, все равно поддержка IDE никакая.

Ява синтаксически архаичная и это не секрет, до сих пор в стандартной библиотеке некоторые модули из принципиальных соображений не поддерживают foreach, появившийся аж лет 8 назад. Наверняка есть сторонние библиотеки ФП, но лямбд и замыканий-то нету.
Есть другие языки на основе JVM, но я сомневаюсь, что по простоте и поддержке IDE они дотягивают до сишарпа/линку.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version