Понимание для сглаживания последовательности последовательностей?

Если у меня есть последовательность последовательностей (возможно, список кортежей), я могу использовать itertools.chain (), чтобы сгладить ее. Но иногда мне кажется, что я скорее напишу это как понимание. Я просто не могу понять, как это сделать. Вот очень понятный случай:

Предположим, я хочу поменять элементы каждой пары в последовательности. Я использую строку как последовательность здесь:

>>> from itertools import chain >>> seq = '012345' >>> swapped_pairs = zip(seq[1::2], seq[::2]) >>> swapped_pairs [('1', '0'), ('3', '2'), ('5', '4')] >>> "".join(chain(*swapped_pairs)) '103254' 

Я использую zip на четных и нечетных участках последовательности, чтобы поменять пары. Но в итоге я получаю список кортежей, которые теперь нужно сгладить. Поэтому я использую chain (). Есть ли способ выразить это с пониманием?

Если вы хотите опубликовать собственное решение основной проблемы обмена элементами пары, продолжайте, я буду голосовать за то, что учит меня чему-то новому. Но я буду отмечать только как принятый ответ, который нацелен на мой вопрос, даже если ответ «Нет, вы не можете».

4 Solutions collect form web for “Понимание для сглаживания последовательности последовательностей?”

С пониманием? Что ж…

 >>> seq = '012345' >>> swapped_pairs = zip(seq[1::2], seq[::2]) >>> ''.join(item for pair in swapped_pairs for item in pair) '103254' 

Самый быстрый, который я нашел, – начать с пустого массива и расширить его:

 In [1]: a = [['abc', 'def'], ['ghi'],['xzy']] In [2]: result = [] In [3]: extend = result.extend In [4]: for l in a: ...: extend(l) ...: In [5]: result Out[5]: ['abc', 'def', 'ghi', 'xzy'] 

Пример этого в два раза быстрее, например, в попытке Alex Martelli: Сделать список из списка списков в Python

 $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]' 10000 loops, best of 3: 86.3 usec per loop $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'b = []' 'extend = b.extend' 'for sub in l:' ' extend(sub)' 10000 loops, best of 3: 36.6 usec per loop 

Я придумал это, потому что у меня была догадка, что за кулисами расширение будет выделять нужное количество памяти для списка и, вероятно, использует некоторый низкоуровневый код для перемещения элементов. Я понятия не имею, верно ли это, но кто заботится, это быстрее.

Кстати, это только линейное ускорение:

 $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]' 'b = []' 'extend = b.extend' 'for sub in l:' ' extend(sub)' 1000000 loops, best of 3: 0.844 usec per loop $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]' '[item for sublist in l for item in sublist]' 1000000 loops, best of 3: 1.56 usec per loop 

Вы также можете использовать map(results.extend, a) , но это медленнее, поскольку она map(results.extend, a) собственный список Nones.

Это также дает вам некоторые преимущества использования функционального программирования. т.е.

  • вы можете расширить существующий список вместо создания пустого,
  • вы все равно можете понять код с первого взгляда, минут, дней или даже месяцев спустя.

Кстати, наверное, лучше всего избегать понимания списков. Маленькие не так уж плохи, но в общем случае списки не на самом деле экономят много печатания, но часто сложнее понять и очень сложно изменить или реорганизовать (когда-либо видели понимание на уровне трех уровней?). Руководства по кодированию Google советуют против них, за исключением простых случаев. Мое мнение состоит в том, что они полезны только в «отбрасывании» кода, то есть в коде, где автор не заботится о читаемости, или о коде, который, как известно, никогда не требует дальнейшего обслуживания.

Сравните эти два способа написания того же:

 result = [item for sublist in l for item in sublist] 

с этим:

 result = [] for sublist in l: for item in sublist: result.append(item) 

YMMV, но первый меня остановил, и я подумал об этом. Во втором гнездование становится очевидным из отступов.

Вы можете использовать сокращение для достижения своей цели:

 In [6]: import operator In [7]: a = [(1, 2), (2,3), (4,5)] In [8]: reduce(operator.add, a, ()) Out[8]: (1, 2, 2, 3, 4, 5) 

Это возвращает кортеж вместо списка, потому что элементы в вашем исходном списке являются кортежами, которые объединяются. Но вы можете легко создать список из этого, и метод join также примет кортежи.

Понимание списка, кстати, не является правильным инструментом для этого. В основном понимание списка создает новый список, описывая, как должны выглядеть элементы этого списка. Вы хотите уменьшить список элементов только до одного значения.

 >>> a = [(1, 2), (3, 4), (5, 6)] >>> reduce(tuple.__add__, a) >>> (1, 2, 3, 4, 5, 6) 

Или, чтобы быть агностиком относительно типа внутренних последовательностей (пока они все одинаковы):

 >>> reduce(a[0].__class__.__add__, a) 
  • пифонический формат для индексов
  • Regex findall start () и end ()? питон
  • Числовой вывод и не повторяют повторяющиеся числа для ex 1010101; 2020202, 1212121
  • Python находит повторяющуюся последовательность в списке целых чисел?
  • Почему словарные значения не находятся в вставленном порядке?
  • Python: программа для поиска LENGTH самого длинного пробега в данном списке?
  • Лучший способ определить, находится ли последовательность в другой последовательности в Python
  • Функция поиска последовательности python
  • Python - лучший язык программирования в мире.