Блог пользователя ilyaraz

Автор ilyaraz, 13 лет назад, По-русски

Обнаружил сегодня забавный момент в Python'е.

Представьте себе, что у вас есть список списков x. Например, x = [[1, 2, 3], [], [[6, 6, 6]]]. Мы хотим сконкатенировать все элементы x и получить в данном случае [1, 2, 3, [6, 6, 6]]. Наука это учит делать красиво: sum(x, []). Действительно, сложение для списков -- это просто-напросто конкатенация.

Однако, у данного подхода есть существенный недостаток. Если, к примеру, у нас k списков константной длины, то sum(x, []) будет работать за время O(k2), а не O(k), как разумеется хотелось бы. Это происходит вот почему: результат сложения списков записывается в новое место, и на выделение памяти каждый раз уходит линейное время. Проблема. Однако, простой цикл спасает положение.

result = []
for element in x: <перенос строки + таб> for item in element: <перенос строки + таб + таб> result.append(item)

Действительно, append работает за учетное время O(1).

Внимание, бонусный вопрос: как сделать конкатенацию всех элементов за время O(k) в "функциональном" стиле?

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Наверное, это будет за линейное время работать. Правда, мне не нравится, что chain будет передаваться k аргументов, но кто его знает, как это в Python реализовано -- может все и будет хорошо.
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Пожалуй, выглядит симпатичнее всего в итоге list(itertools.chain.from_iterable(x)).
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
result.extend(element)


  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Не понимаю, чем extend нам поможет.
    • 13 лет назад, # ^ |
      Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

      In [111]: x = [[1, 2, 3], [], [[6, 6, 6]]]

      In [112]: result = []

      In [113]: for a in x: result.append(a)

         .....: 

      In [114]: result

      Out[114]: [[1, 2, 3], [], [[6, 6, 6]]]

      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Ой, я все напутал, конечно, там нужен еще один for. Сейчас исправлю, спасибо.