На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: RaD
  
    > [Python] Свой zip() , С кирпичами и цементом
      Продолжаю мучить Python. Решил вот для разнообразия написать свой аналог zip.

      ExpandedWrap disabled
        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. Можно ли без них обойтись?
        Посмотри описание zip в документации. Там должна быть реализация, эквивалентная встроенной функции.

        И, когда генерируешь кортеж, не надо в него список. То есть квадратные списки в вызове tuple можно опустить.
          Цитата amk @
          И, когда генерируешь кортеж, не надо в него список. То есть квадратные списки в вызове tuple можно опустить.

          Ок, спасибо. Просто забыл, что конструктор кортежа кушает итератор. А выражение вида
          ExpandedWrap disabled
            t = (i for i in range(5))
            print (t)

          вернет <generator object <genexpr> at 0x170c0f0>
          Поэтому что-то на автомате в лист воткнул как-то :)

          А вот реализации я что-то не нашел:
          http://docs.python.org/library/functions.html#zip

          help(zip) тоже не содержит аналога
            Видимо эквиваленты только в 3-м питоне включили. В нем
            ExpandedWrap disabled
              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 генерирует список всех комбинаций, и возвращает его.

            То есть получится что-то вроде
            ExpandedWrap disabled
              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
            Проверить не могу, у меня 3.2.2
              Как написано, оно на 2.7 бесконечный цикл улетает. Вот так работает:

              ExpandedWrap disabled
                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() в питоне?
                crawler, а тебе не кажется, что None может оказаться в списке? Иначе зачем ты думаешь там в коде для Py3 sentinel создавался?

                И кстати, кто там о бесконечном цикле пишет? Если он бесконечный, то программа просто не выйдет из этой функции.
                Замени 'break' в моем коде на 'return alltuples'. Там ошибка, нужно рвать оба цикла, а не только внутренний.
                  Цитата amk @
                  И кстати, кто там о бесконечном цикле пишет? Если он бесконечный, то программа просто не выйдет из этой функции.

                  Ну, так и было. Он начал стремительно жрать память, потом улетел в своп, и секунд 30 я пытался перейти в другую консоль, чтобы убить процесс. Просто "while iterables:" всегда было True.

                  Между делом почитал книжку, а там, оказывается, вопрос решен давно:

                  ExpandedWrap disabled
                    def myzip(*seqs):
                        minlen = min(len(s) for s in seqs)
                        return [ tuple(s[i] for s in seqs) for i in range(minlen) ]

                  Или по аналогии:
                  ExpandedWrap disabled
                    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'. Там ошибка, нужно рвать оба цикла, а не только внутренний.

                  Заменил, работает :)
                  1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0263 ]   [ 14 queries used ]   [ Generated: 18.07.25, 05:01 GMT ]