Найти - Пользователи
Полная версия: Клонирование итератора
Начало » Python для экспертов » Клонирование итератора
1 2 3 4
Isem
Ed
def minmax3(iterable):
isorted = sorted(iterable)
return isorted, isorted
Этот вариант так быстро сработал потому, что сам по себе список уже отсортированный. Если ему подсунуть случайный список, то время увеличивается раз в 10
Ed
Насчет не менее читабельного вы явно погорячились.
Я про первый вариант вообще молчу, но даже во втором вот это:
functools.reduce( cmp, it, 2*(it[0],) ) if it else None
читабельным можно назвать с большой натяжкой. Впрочем, наверное это субъективно.
Isem
Ed
1. Напишите лямбда функцию
2. Напишите комментарий, объясняющий что за хренотень она делает.
3. Поизучайте комментарий какое-то время и подумайте об имени, которое бы показывало сущность коментария
4. Преобразуйте вашу лямбду в обычную функцию, используя это имя
5. Удалите комментарий
:)

Для случайного списка результат таков:

result for minmax of shuffled list: (0, 1999999), ‘time spent:0.825999975204
result for minmax1 of shuffled list: (0, 1999999), ’time spent:0.703999996185
result for minmax2 of shuffled list: (0, 1999999), ‘time spent:0.604000091553
result for minmax3 of shuffled list: (0, 1999999), ’time spent:3.10199999809
Ed
У меня получается так:
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 ))
Isem
Можно сделать вывод, что функции min и max реализованы на си и особенно эффективны для больших списков. Однако их частый вызов в циклах для коротких списков приводит к заметному снижению производительности.
Isem
Если вашу функцию переписать вот так:
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
Ed
У меня такое извращение показало наименьшее время:
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
result for minmax1: (0, 1999999), ‘time spent:0.870595932007
result for minmax2: (0, 1999999), ’time spent:0.919430017471
result for minmax3: (0, 1999999), ‘time spent:3.98846888542
result for minmax4: (0, 1999999), ’time spent:1.37609004974
result for minmax5: (0, 1999999), 'time spent:0.659359931946
Ed
Так нехорошо: minm = iterable
Сразу исчезает возможность работать с итераторами.
Isem
А в третьем питоне это работает прекрасно.
Например ragne(100) дает 3, хотя range() возвращает именно итератор
Конечно, это обращение по времени как o(n), но для первого элемента (точнее нулевого) - нормально
Isem
Есть такая интересная задачка. Допустим, есть итератор, довольно сложный, который генерирует, например, длинные строки (1000 символов каждая, скажем).
Нужно определить длину цикла этого итератора. Но надо учитывать, что цикл может начинаться (и заканчиваться, соответственно) не с первого элемента, а совсем с другого. Сама же последовательность итератора может быть очень длинная.
Вот упрощенный (цифровой) пример списка, который генерирует итератор: ( 61,7,3,5,48, 54,34,62,221,31,67, 54,34,62,221,31,67, 54……. и т.д.)
Видно, что цикл начинается с числа 54 и длина цикла равна 6.
Возможно, это оффтопик для данной ветки, однако же все равно она бы умерла, если бы мы ее не оживили.:)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB