Вопрос по list-comprehension, python – Как мне объединить 2D-массив в Python в одну строку с помощью списка понимания?

16

Понимание списка для меня похоже на непрозрачный гранитный блок, которым являются регулярные выражения для меня. Мне нужны указатели.

Скажем, у меня есть список 2D:

li = [[0,1,2],[3,4,5],[6,7,8]]

Я хотел бы объединить это либо в один длинный список

li2 = [0,1,2,3,4,5,6,7,8]

или в строку с разделителями:

s = "0,1,2,3,4,5,6,7,8"

Действительно, я хотел бы знать, как сделать то и другое.

В подкасте № 1 Джоэл задает этот точный вопрос как вопрос, который можно ввести в Google, чтобы получить переполнение стека в качестве первого результата ... и это так :-) Yuval

Ваш Ответ

8   ответов
26

Вот так:

[ item for innerlist in outerlist for item in innerlist ]

Превращая это непосредственно в строку с разделителями:

','.join(str(item) for innerlist in outerlist for item in innerlist)

Да, порядок 'для внутреннего списка во внешнем списке' и "для элемента во внутреннем списке"; верно. Даже если «тело» цикла находится в начале listcomp, порядок вложенных циклов (и «if» выражений) все тот же, что и при записи цикла:

for innerlist in outerlist:
    for item in innerlist:
        ...
прикомандирован. Я хотел бы, чтобы мне понравился этот ответ не раз!
Спасибо! Этот порядок никогда не имел никакого смысла для меня, пока вы не объяснили это так.
Это невероятно.
0

>>> print ','.join(str(x) for x in li2)
"0,1,2,3,4,5,6,7,8"

Для первого вы можете использовать соединение в списке понимания:

>>> print ",".join([",".join(str(x) for x in li])
"0,1,2,3,4,5,6,7,8"

Но проще использовать itertools.flatten:

>>> import itertools
>>> print itertools.flatten(li)
[0,1,2,3,4,5,6,7,8]
>>> print ",".join(str(x) for x in itertools.flatten(li))
"0,1,2,3,4,5,6,7,8"

Примечание: itertools - это модуль, который помогает вам решать общие задачи с итераторами, такими как список, кортежи или строки ... Это удобно, потому что он не хранит копию структуры, над которой вы работаете, а обрабатывает элементы один. одним.

РЕДАКТИРОВАТЬ: смешно, я учусь много способов сделать это. Кто сказал, что есть только один хороший способ сделать это?

Какую версию Python вы используете, у которой есть itertools.flatten? Насколько я вижу, это не является частью стандартной библиотеки. Кроме того, высказывание «один очевидный способ», который сильно отличается от «хорошего».
4

Мой любимый и самый короткий, это:

li2 = sum(li, [])

а также

s = ','.join(li2)

РЕДАКТИРОВАТЬ: использоватьsum вместоreduce, (СпасибоТомас Воутерс!)

Этот подход проще сделать с помощью sum: sum (li, [])
Это не работает: & lt; тип & исключений.TypeError & gt ;: redu () arg 2 должен поддерживать итерацию
0

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

import numpy
li = [[0,1,2],[3,4,5],[6,7,8]]
li2=li[0] #first element of array to merge
i=1 
while i<len(li):
    li2=numpy.concatenate((li2,li[i]))
    i+=1
print li2

Это напечатало бы [0 1 2 3 4 5 6 7 8], а затем вы также можете преобразовать это в вашу строку.

0

Чтобы сделать его сплющенным списком, используйте либо:

http://code.activestate.com/recipes/121294/ http://code.activestate.com/recipes/363051/

Затем,join сделать это строкой.

Я не вижу функции сглаживания в itertools. Я использую Python 2.4.2
6

Попробуй это:

li=[[0,1,2],[3,4,5],[6,7,8]]
li2 = [ y for x in li for y in x]

Вы можете прочитать это так:
Дайте мне список каждого.
Ys приходят от хз.
Икс происходят из ли.

Чтобы отобразить это в строке:

','.join(map(str,li2))
5

Есть несколько вариантов. Во-первых, вы можете просто создать новый список и добавить в него содержимое каждого списка:

li2 = []
for sublist in li:
    li2.extend(sublist)

Кроме того, вы можете использоватьitertools Модуль & APOS; schain функция, которая создает итерацию, содержащую все элементы в нескольких итерациях:

import itertools
li2 = list(itertools.chain(*li))

Если вы воспользуетесь этим подходом, вы можете создать строку без создания промежуточного списка:

s = ",".join(itertools.chain(*li))
Легко решаемо: "," .join (itertools.imap (str, itertools.chain (* li)))
Идея хорошая, но она вылетает, потому что вы не взяли машину с типом данных: & lt; type & apos; exceptions.TypeError & apos; & gt ;: item sequence 0: ожидаемая строка, int найдено
-1
import itertools
itertools.flatten( li )
Там нет itertools.flatten.
Я думаю, что он говорит о примерной функции, показанной в документах itertools:docs.python.org/library/itertools.html  В любом случае, не основанный на списках.

Похожие вопросы