Преобразование многомерного списка в одномерный список в Python - PullRequest
30 голосов
/ 03 июня 2010

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

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

Ответы [ 7 ]

43 голосов
/ 03 июня 2010

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

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

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

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

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

35 голосов
/ 03 июня 2010

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' и 'list'

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

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

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

Примечание

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

Обновление

Чтобы выровнять 1 уровень вложенности, см. Этот рецепт со страницы itertools :

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

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

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

2 голосов
/ 15 ноября 2016

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

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 []
1 голос
/ 18 июня 2010

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

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 голос
/ 03 июня 2010

Мне кажется, что вы ищете окончательный ответ:

[3, 7]

Для этого вам лучше всего понять список

>>> l=[[1,2],[3,4]]
>>> [x+y for x,y in l]
[3, 7]
0 голосов
/ 07 февраля 2019

Я написал эту функцию:

def make_array_single_dimension(l):
    l2 = []

    for x in l:
        if type(x).__name__ == "list":
            l2 += make_array_single_dimension(x)
        else:
            l2.append(x)

    return l2

Так же работает!

0 голосов
/ 01 сентября 2017

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...