2010-06-02 2 views
27

Многомерный список, например l=[[1,2],[3,4]], может быть преобразован в 1D, выполнив sum(l,[]). Может ли кто-нибудь объяснить, как это происходит?Преобразование многомерного списка в 1D-список в Python

Ответчик сказал, что этот метод можно использовать только для «сглаживания» 2D-списка - что он не будет работать для более высоких многомерных списков. Но это происходит, если повторять. Например, если A является 3D-списком, тогда сумма (сумма (A), []), []) сгладит A до 1D-списка.

+5

Это не превратит * любой * многомерный список в 1D. '[[[1,2]], [[3,4]]]' становится '[[1, 2], [3, 4]]'. – Ponkadoodle

+1

Также обратите внимание, что небезопасно преобразовывать только последовательность _any_ в 1D, так как тривиально создавать последовательности с поистине бесконечным числом измерений: 'a = []; a.append (а) '. – badp

+0

Связанный «Сглаживание мелкого списка в python» http://stackoverflow.com/questions/406121/flattening-a-shallow-list-in-python – jfs

ответ

33

sum добавляет последовательность вместе с использованием оператора +. например, sum([1,2,3]) == 6. Второй параметр является необязательным начальным значением, которое по умолчанию равно 0. например. sum([1,2,3], 10) == 16.

В вашем примере это [] + [1,2] + [3,4], где + в 2 списках объединяет их вместе. Поэтому результат [1,2,3,4]

Пустой список требуется в качестве 2-го параметра Я к sum, потому что, как уже упоминалось выше, по умолчанию для sum добавить в 0 (т.е. 0 + [1,2] + [3,4]), что приведет к неподдерживаемый тип операнда (s) для +: 'Int' и 'список'

Это соответствующий раздел помощи для sum:

сумма (последовательность [, начало]) -> значение

Возвращает сумму последовательности номеров (НЕ строки) плюс значение параметра 'start' (по умолчанию - 0).

Примечание

Как wallacoloo comented это не общее решение для выпрямления любого многомерные списка. Он просто работает для списка 1D-списков из-за поведения, описанного выше.

Update

На пути к сплющить 1 уровень вложенности см этот рецепт от itertools страницы:

def flatten(listOfLists): 
    "Flatten one level of nesting" 
    return chain.from_iterable(listOfLists) 

сглаживаться более глубоко вложенной списки (в том числе неправильно вложенных списков) см accepted answer до this question (есть и другие вопросы, связанные с этим вопросом.)

Обратите внимание, что в рецепте возвращается номер itertools.chain (итерабельный), а ответ другого вопроса возвращает объект generator, поэтому вам нужно обернуть любой из них при вызове list, если вам нужен полный список, а не итерация по нему. например list(flatten(my_list_of_lists)).

+0

Большое спасибо, понял. Могу ли я спросить, что является самым коротким и лучшим способом сгладить список? В настоящее время я могу только думать о запуске двух вложенных циклов или рекурсивной функции для этого. – Sayan

+0

Я сделал быстрое обновление ответа с рецептом для выравнивания 1 уровня вложенности и ссылки на предыдущий вопрос SO с более общим решением. – mikej

1

Она смотрит на меня больше как вы ищете для окончательного ответа:

[3, 7] 

За что ты лучше от с list comprehension

>>> l=[[1,2],[3,4]] 
>>> [x+y for x,y in l] 
[3, 7] 
+0

Нет, не очень, я пытался найти более короткую/лучшую альтернативу, чтобы сгладить 2D-список. Я заполняю список, содержащий триплеты, в другой список (например, [[1,2,3], [4,5,6], [7,8,9]]), и я бы не стал вводить число, если оно уже существующих в этом списке. Поэтому моя цель - поставить что-то вроде ... Спасибо в любом случае :) – Sayan

+1

@Sayan Тогда вам не нужны списки, вы хотите 'set's. – badp

+0

До сих пор я ничего не знал о наборах Python. Спасибо за направление. – Sayan

40

Если список nested есть, как вы говорите, «2D» (это означает, что вы хотите идти только на один уровень вниз, а все позиции с 1 уровнем вниз из nested - это списки), простое понимание списка:

flat = [x for sublist in nested for x in sublist] 

является подход, который я рекомендовал бы - гораздо эффективнее, чем sum мина будет (sum предназначен для чисел - это было просто слишком много потрудился как-то сделать его блокировать все попытки «сумма» non-numbers ... Я был оригинальным автором и первым разработчиком sum в стандартной библиотеке Python, поэтому, я думаю, я должен знать ;-).

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

This recipe предлагает рекурсивное решение, устранение рекурсии и другие подходы (все поучительно, хотя и не так просто, как однострочный, предложенный ранее в этом ответе).

+0

А я был уверен, что смогу это сделать, используя понимание списка, но испортил код. Спасибо и привилегия! – Sayan

+0

@ alex-martelli, это решение отлично работает, но мне трудно понять. Не могли бы вы пропустить меня через порядок операций, который должен выполнять python при выполнении этого решения? – NobodyMan

+2

@NobodyMan, конечно, это всего лишь две вложенные петли: точно так же, как в внешнем выражении 'для подписок в вложенном:' вы отделили еще один оператор 'for x в sublist:', а затем внутри него просто взялось главное выражение 'x' из списка, которое будет добавлено в качестве следующего элемента нового списка, который вы строите. Другими словами, он работает точно так же, как и любое другое понимание списка с двумя предложениями 'for', хотя ведущее выражение перед предложениями' for' в этом случае чрезвычайно просто :-). –

0

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

def flatten(l): 
    lf=[] 
    li=[] 
    ll=[] 
    p=0 
    for i in l: 
     if type(i).__name__=='list': 
      li.append(i) 
     else: 
      lf.append(i) 
    ll=[x for i in li for x in i] 
    lf.extend(ll) 

    for i in lf: 
     if type(i).__name__ =='list': 
      #not completely flattened 
      flatten(lf) 
     else: 
      p=p+1 
      continue 

    if p==len(lf): 
     print(lf) 
1

Для любого вида multidiamentional массива, этот код будет делать уплощение в одном измерении:

def flatten(l): 
    try: 
     return flatten(l[0]) + (flatten(l[1:]) if len(l) > 1 else []) if type(l) is list else [l] 
    except IndexError: 
     return [] 
0

Оператор + объединяет списки, а начальное значение [] - пустой список.

Смежные вопросы