
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.30] |
![]() |
|
Сообщ.
#1
,
|
|
|
Продолжаю мучить Python. Решил вот для разнообразия написать свой аналог zip.
![]() ![]() def myzip(*args): l = [] lenlist = [ len(i) for i in args ] maxlen = max(lenlist) for i in range(maxlen): l.append( tuple ( [ arg[i] if i<lenlist[id] else None for (id,arg) in enumerate(args) ] ) ) return l l1 = [1,1,1,1] l2 = [2,2,2,2] l3 = [3,3,3,3,4] #print ( *myzip(*myzip(l1,l2,l3)) ) print ( myzip(l1,l2,l3) ) Мне не нравится то, что используются индексы и enumerate. Можно ли без них обойтись? |
Сообщ.
#2
,
|
|
|
Посмотри описание zip в документации. Там должна быть реализация, эквивалентная встроенной функции.
И, когда генерируешь кортеж, не надо в него список. То есть квадратные списки в вызове tuple можно опустить. |
Сообщ.
#3
,
|
|
|
Цитата amk @ И, когда генерируешь кортеж, не надо в него список. То есть квадратные списки в вызове tuple можно опустить. Ок, спасибо. Просто забыл, что конструктор кортежа кушает итератор. А выражение вида ![]() ![]() t = (i for i in range(5)) print (t) вернет <generator object <genexpr> at 0x170c0f0> Поэтому что-то на автомате в лист воткнул как-то ![]() А вот реализации я что-то не нашел: http://docs.python.org/library/functions.html#zip help(zip) тоже не содержит аналога |
Сообщ.
#4
,
|
|
|
Видимо эквиваленты только в 3-м питоне включили. В нем
![]() ![]() def zip(*iterables): "zip('ABCD', 'xy') --> Ax By" sentinel = object() iterables = [iter(it) for it in iterables] while iterables: result = [] for it in iterables: elem = next(it, sentinel) if elem is sentinel: return result.append(elem) yield tuple(result) Во втором, насколько помню zip генерирует список всех комбинаций, и возвращает его. То есть получится что-то вроде ![]() ![]() def zip(*iterables): "zip('ABCD', 'xy') --> Ax By" sentinel = object() iterables = [iter(it) for it in iterables] alltuples = [] while iterables: result = [] for it in iterables: elem = next(it, sentinel) if elem is sentinel: break result.append(elem) alltuples.append(tuple(result)) return alltuples |
Сообщ.
#5
,
|
|
|
Как написано, оно на 2.7 бесконечный цикл улетает. Вот так работает:
![]() ![]() def myzip(*iterables): #sentinel = object() iterables = [iter(it) for it in iterables] alltuples = [] c = 0 while True: # any(iterables): # c += 1 # if c > 1000: return res = [] for i in iterables: elem = next(i, None) if not i: print ('not i!') res.append(elem) if not any(res): return alltuples alltuples.append(tuple(res)) return alltuples Проблема в том, что "not i!" не вывелось ни разу, т.е. если итератор в самом конце, то он !False. Нет ли какого-нибудь atend() в питоне? |
Сообщ.
#6
,
|
|
|
crawler, а тебе не кажется, что None может оказаться в списке? Иначе зачем ты думаешь там в коде для Py3 sentinel создавался?
И кстати, кто там о бесконечном цикле пишет? Если он бесконечный, то программа просто не выйдет из этой функции. Замени 'break' в моем коде на 'return alltuples'. Там ошибка, нужно рвать оба цикла, а не только внутренний. |
Сообщ.
#7
,
|
|
|
Цитата amk @ И кстати, кто там о бесконечном цикле пишет? Если он бесконечный, то программа просто не выйдет из этой функции. Ну, так и было. Он начал стремительно жрать память, потом улетел в своп, и секунд 30 я пытался перейти в другую консоль, чтобы убить процесс. Просто "while iterables:" всегда было True. Между делом почитал книжку, а там, оказывается, вопрос решен давно: ![]() ![]() def myzip(*seqs): minlen = min(len(s) for s in seqs) return [ tuple(s[i] for s in seqs) for i in range(minlen) ] Или по аналогии: ![]() ![]() def myzip(*args, **kwargs): maxlen = max( len(arg) for arg in args ) pad = kwargs.get('pad', None) return [ tuple(arg[i] if i<len(arg) else pad for arg in args) for i in range(maxlen) ] Цитата amk @ Замени 'break' в моем коде на 'return alltuples'. Там ошибка, нужно рвать оба цикла, а не только внутренний. Заменил, работает ![]() |