2016-11-05 3 views
0

скажите a = [[1, 1, 1, 6], [0, 2, -1, 3], [4, 0, 10, 42]] и я хочу перенести его на a = [[1, 0,4], [1,2,0], [1, -1,10], [6,3,42]] с использованием петель в python. Текущий код, который у меня есть:Как перенести массив 2D-списка с использованием циклов в python?

def transpose(a): 
    s = [] 
    for row in range(len(a)): 
     for col in range(len(a)): 
      s = s + [a[col][row]] 
return s 

Но это дает мне выход:

[1, 0, 4, 1, 2, 0, 1, -1, 10] 

Вместо этого:

[[1,0,4], [1,2,0], [1,-1,10], [6,3,42]] 

Может кто-нибудь мне помочь? Я все еще новичок в этом и не понимаю, почему это не работает. Спасибо!

ответ

0

Использование zip()

>>> a = [[1, 1, 1, 6], [0, 2, -1, 3], [4, 0, 10, 42]] 
>>> [list(x) for x in zip(*a)] 
[[1, 0, 4], [1, 2, 0], [1, -1, 10], [6, 3, 42]] 

zip(*a) распаковывает три суб-листы в a и объединяет их поэлементно. Смысл, первые элементы каждого из трех подписок объединены вместе, а другие элементы объединены вместе и так далее. Но zip() возвращает кортежи вместо списков, как вы хотите в своем выходе. Как это:

>>> zip(*a) 
[(1, 0, 4), (1, 2, 0), (1, -1, 10), (6, 3, 42)] 

[list(x) for x in zip(*a)] преобразует каждый из кортежей списков, давая выходной сигнал так, как вам это нужно.

+0

Я знаю, что это один из способов сделать это, но есть другой способ сделать это использование для циклов или циклов? – Catury

+0

Другой ответ касается вашего вопроса. Вы видите один список на своем выходе, потому что вы не создаете список во внутреннем цикле. – shaktimaan

1

Вот решение, которое основано на коде:

def transpose(a): 
    s = [] 
    # We need to assume that each inner list has the same size for this to work 
    size = len(a[0]) 
    for col in range(size): 
     inner = [] 
     for row in range(len(a)): 
      inner.append(a[row][col]) 
     s.append(inner) 
    return s 

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

[[1, 0, 4], [1, 2, 0], [1, -1, 10], [6, 3, 42]] 
+0

Вместо inner.append и s.append, inner = inner + [a [row] [col]] и s = s + [internal] работает одинаково! Спасибо!! – Catury

+0

Я бы не сказал, что он работает * точно так же - вы можете взглянуть на [это] (https://stackoverflow.com/questions/2022031/python-append-vs-operator-on- списки-why-do-these-give-different-results/2022044 # 2022044) полезный ответ, объясняющий различия. – Maurice

+0

@Catury: Он работает не так. Когда вы делаете 'list = list + [l]', он создает новый список со значением 'list' и' l' и присваивает новый список 'list'. где 'list.append (l)' добавляет 'l' в существующий список' list' –

0

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

>>> a = [[1, 1, 1, 6], [0, 2, -1, 3], [4, 0, 10, 42]] 
>>> sublist_size = len(a[0]) 
>>> [[item[i] for item in a] for i in range(sublist_size)] 
[[1, 0, 4], [1, 2, 0], [1, -1, 10], [6, 3, 42]] 

Однако, самый простой способ заключается в использовании zip():

>>> list(zip(*a)) # for Python 3, OR, just zip(*a) in Python 2 
[(1, 0, 4), (1, 2, 0), (1, -1, 10), (6, 3, 42)] 
+0

Немного короче b = [[i [j] для i в a] для j в диапазоне (len (a) +1)] – JackTheCrab

+1

@JackTheCrab: Нет необходимости, чтобы длина подписок была еще 1, что длина списка (хотя и в этом примере). Поэтому 'range (len (a [0]))' следует использовать вместо 'range (len (a) + 1)'. Вложенные два шага и сокращение имени переменной для уменьшения одной строки кода; Это не хорошая практика. Короче не всегда хорошо.Если более крупный (в очень малой степени) код более читабельный, пойдите для большего;) –

+0

Вы правы, спасибо, что указали это. Определенно соглашаться на удобочитаемость;) – JackTheCrab

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