Форум сайта python.su
EdЭтот вариант так быстро сработал потому, что сам по себе список уже отсортированный. Если ему подсунуть случайный список, то время увеличивается раз в 10
def minmax3(iterable):
isorted = sorted(iterable)
return isorted, isorted
Офлайн
Насчет не менее читабельного вы явно погорячились.
Я про первый вариант вообще молчу, но даже во втором вот это:
functools.reduce( cmp, it, 2*(it[0],) ) if it else None
Офлайн
Ed:)
1. Напишите лямбда функцию
2. Напишите комментарий, объясняющий что за хренотень она делает.
3. Поизучайте комментарий какое-то время и подумайте об имени, которое бы показывало сущность коментария
4. Преобразуйте вашу лямбду в обычную функцию, используя это имя
5. Удалите комментарий
Офлайн
У меня получается так:
result for minmax: (0, 1999999), ‘time spent:7.46938109398
result for minmax1: (0, 1999999), ’time spent:0.92161488533
result for minmax2: (0, 1999999), ‘time spent:0.899652004242
result for minmax3: (0, 1999999), ’time spent:3.92543697357
result for minmax4: (0, 1999999), 'time spent:1.45591902733
Для такого кода:
import functools
import random
from time import time
def minmax1(iterable):
minm = None
maxm = None
for item in iterable:
if maxm is None or item > maxm:
maxm = item
if minm is None or item < minm:
minm = item
return minm, maxm
def minmax( it, key = lambda self: self ):
return functools.reduce( lambda pair, x: (x,x) if pair is None else ( +min(x, pair[0], key=key), max(x, pair[1], key=key) ), it, None )
def minmax2(iterable):
return min(iterable), max(iterable)
def minmax3(iterable):
isorted = sorted(iterable)
return isorted[0], isorted[-1]
def minmax4(it):
def cmp( pair, x ):
if x < pair[0]: return x, pair[1]
if x > pair[1]: return pair[0], x
return pair
return functools.reduce( cmp, it, 2*(it[0],) ) if it else None
data = range(2000000)
random.shuffle(data)
for fun in minmax, minmax1, minmax2, minmax3, minmax4:
start = time()
print("result for {0}: {1}, 'time spent:{2}".format( fun.__name__, fun(data), time() - start ))
Офлайн
Можно сделать вывод, что функции min и max реализованы на си и особенно эффективны для больших списков. Однако их частый вызов в циклах для коротких списков приводит к заметному снижению производительности.
Офлайн
Если вашу функцию переписать вот так:
def minmax1(iterable):
if not iterable: return (None, None)
minm = iterable
maxm = minm
for item in iterable:
if item > maxm:
maxm = item
if item < minm:
minm = item
return minm, maxm
то она начинает работать быстрее двухпроходной:
result for minmax of shuffled list: (0, 1999999), ‘time spent:0.819000005722
result for minmax1 of shuffled list: (0, 1999999), ’time spent:0.514000177383
result for minmax2 of shuffled list: (0, 1999999), 'time spent:0.598000049591
Офлайн
У меня такое извращение показало наименьшее время:
def minmax5(iterable):
itera = iter(iterable)
minm = maxm = itera.next()
for item in itera:
if item > maxm:
maxm = item
elif item < minm:
minm = item
return minm, maxm
Офлайн
Так нехорошо: minm = iterable
Сразу исчезает возможность работать с итераторами.
Офлайн
А в третьем питоне это работает прекрасно.
Например ragne(100) дает 3, хотя range() возвращает именно итератор
Конечно, это обращение по времени как o(n), но для первого элемента (точнее нулевого) - нормально
Офлайн
Есть такая интересная задачка. Допустим, есть итератор, довольно сложный, который генерирует, например, длинные строки (1000 символов каждая, скажем).
Нужно определить длину цикла этого итератора. Но надо учитывать, что цикл может начинаться (и заканчиваться, соответственно) не с первого элемента, а совсем с другого. Сама же последовательность итератора может быть очень длинная.
Вот упрощенный (цифровой) пример списка, который генерирует итератор: ( 61,7,3,5,48, 54,34,62,221,31,67, 54,34,62,221,31,67, 54……. и т.д.)
Видно, что цикл начинается с числа 54 и длина цикла равна 6.
Возможно, это оффтопик для данной ветки, однако же все равно она бы умерла, если бы мы ее не оживили.:)
Отредактировано (Авг. 27, 2010 19:57:03)
Офлайн