リストの転置リスト


241

取りましょう:

l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

私が探している結果は

r = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

ではなく

r = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

とても有難い

回答:


336

いかがですか

map(list, zip(*l))
--> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Python 3.xの場合、ユーザーは次を使用できます

list(map(list, zip(*l)))

説明:

何が起こっているのかを理解するために知っておくべきことが2つあります。

  1. zipの署名:zip(*iterables)これzipは、それぞれが反復可能でなければならない任意の数の引数を期待することを意味します。例えばzip([1, 2], [3, 4], [5, 6])
  2. アンパックされた引数リスト:一連の引数を指定すると、の各要素がの個別の位置引数になるようargsf(*args)が呼び出さfargsますf

質問からの入力に戻ることはl = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]zip(*l)と同等zip([1, 2, 3], [4, 5, 6], [7, 8, 9])です。残りは、結果がタプルのリストではなくリストのリストであることを確認するだけです。


67
注意:lサイズが均一でない場合(たとえば、一部の行が他の行よりも短い場合)zipそれを補正せず、代わりに出力から行を削除します。だからl=[[1,2],[3,4],[5]]あなたに与える[[1,3,5]]
badp

29
itertoolsこの関数はzip_longest()、凹凸のリストで動作します。参照してくださいDOCS
オレガノ

13
答えの説明はいいでしょう:)
ボリス・チャージン

7
私もが思うlist(zip(*l))のPython 3で正常に動作する
ステファノ

3
@Stefano(zip(*l)Python 2と同様に)機能しますが、リストのリストではなく、タプルのリストを取得します。もちろん、list(list(it))は常にと同じですlist(it)
Alex Shpilkin

62

これを行う1つの方法は、NumPyトランスポーズを使用することです。リストの場合:

>>> import numpy as np
>>> np.array(a).T.tolist()
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

または、zipなしの別のもの:

>>> map(list,map(None,*a))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

8
2つ目が大好きです-それがmapできるとは思いもしませんでした。ここでは、しかし、2つのコールを必要としないわずかな改良があります:map(lambda *a: list(a), *l)
リーD

7
不均一なリストを処理するので、これはより良い答えではないでしょうか?
Leon

15
map(None, ...)Py3では動作しないようです。ジェネレータは作成されますがnext()、すぐにエラーが発生しますTypeError: 'NoneType' object is not callable
Mad Physicist

57

イエナのソリューションと同等:

>>> l=[[1,2,3],[4,5,6],[7,8,9]]
>>> [list(i) for i in zip(*l)]
... [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

12
リスト内包表記がに優先されるようになったためmap()、この解決策はPython精神の中で最も高いものです...
perror

26

面白さのために、有効な長方形とm [0]が存在すると仮定

>>> m = [[1,2,3],[4,5,6],[7,8,9]]
>>> [[row[i] for row in m] for i in range(len(m[0]))]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

これは私が探していたもので、頭を動かすことができませんでした。それでも@jenaの解決策は本当に短いです
titus

3
ええ、これを正しくするためにいくつかのタイヤが必要でした。さて、多くの試み。
マッチ

9
それでもまだ正しくありません。これは、寸法が正方形の場合にのみ機能します。次のようになります[[j[i] for j in l] for i in range(len(l[0]))]。もちろん、リストlが空でないことを確認する必要があります。
リーD

@LeeDは、jenaの例ではまだ機能しませんl = [[1,2]、[3,4]、[5]]
ホブ

3
@hobsそれはbadaの例で、イエナに応答しました。しかし、それが私にとって意味があるかどうかはわかりません。IMO、転置は長方形の行列を意味します-リストのリストとして表される場合、すべての内部リストは同じ長さでなければなりません。この例の「転置」としてどのような結果を望みますか?
Lee D

22

メソッド1と2はPython 2または3で機能し、不規則な長方形の 2Dリストで機能します。つまり、内部リストは互いに(不揃い)または外部リスト(長方形)と同じ長さである必要はありません。他の方法も、複雑です。

セットアップ

import itertools
import six

list_list = [[1,2,3], [4,5,6, 6.1, 6.2, 6.3], [7,8,9]]

方法1 — map()zip_longest()

>>> list(map(list, six.moves.zip_longest(*list_list, fillvalue='-')))
[[1, 4, 7], [2, 5, 8], [3, 6, 9], ['-', 6.1, '-'], ['-', 6.2, '-'], ['-', 6.3, '-']]

six.moves.zip_longest() なる

デフォルトのfillvalueはNoneです。@イエナさんのおかげで答えmap()リストに内側のタプルを変更しています。ここでは、イテレータをリストに変えています。@Oreganoと@badpのコメントに感謝します

Python 3では、list()メソッド2と同じ2Dリストを取得するために結果を渡します。


方法2 —リスト内包、 zip_longest()

>>> [list(row) for row in six.moves.zip_longest(*list_list, fillvalue='-')]
[[1, 4, 7], [2, 5, 8], [3, 6, 9], ['-', 6.1, '-'], ['-', 6.2, '-'], ['-', 6.3, '-']]

inspectorG4dget代替@


メソッド3 — map()of map()Python 3.6で壊れています

>>> map(list, map(None, *list_list))
[[1, 4, 7], [2, 5, 8], [3, 6, 9], [None, 6.1, None], [None, 6.2, None], [None, 6.3, None]]

この非常にコンパクトな@SiggyFの2番目の代替方法は、numpyを使用して不規則なリストを転置および通過させる最初のコードとは異なり、不規則な2Dリストで機能します。しかし、どれも塗りつぶしの値である必要はありません。(いいえ、内部のmap()に渡されるNoneは塗りつぶしの値ではありません。これは、各列を処理する関数がないことを意味します。列は外部のmap()に渡されるだけで、タプルからリストに変換されます。

Python 3のどこかで、map()このすべての悪用を我慢しなくなりました。最初のパラメーターをNoneにすることはできず、不規則なイテレーターは最短に切り捨てられるだけです。これは内部のmap()にのみ適用されるため、他のメソッドは引き続き機能します。


方法4 - map()map()再考

>>> list(map(list, map(lambda *args: args, *list_list)))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]   // Python 2.7
[[1, 4, 7], [2, 5, 8], [3, 6, 9], [None, 6.1, None], [None, 6.2, None], [None, 6.3, None]] // 3.6+

残念ながら、不揃いな行はPython 3では不揃いな列にはなりません。それらは単に切り捨てられます。ブーフー進歩。


7

選択できる3つのオプション:

1. Zipでマップ

solution1 = map(list, zip(*l))

2.リストの理解

solution2 = [list(i) for i in zip(*l)]

3.ループの追加

solution3 = []
for i in zip(*l):
    solution3.append((list(i)))

結果を表示するには:

print(*solution1)
print(*solution2)
print(*solution3)

# [1, 4, 7], [2, 5, 8], [3, 6, 9]

0

おそらく最もエレガントな解決策ではないかもしれませんが、ネストされたwhileループを使用した解決策を次に示します。

def transpose(lst):
    newlist = []
    i = 0
    while i < len(lst):
        j = 0
        colvec = []
        while j < len(lst):
            colvec.append(lst[j][i])
            j = j + 1
        newlist.append(colvec)
        i = i + 1
    return newlist


0

more_itertools.unzip() 読みやすく、ジェネレーターでも動作します。

import more_itertools
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
r = more_itertools.unzip(l) # a tuple of generators.
r = list(map(list, r))      # a list of lists

または同等に

import more_itertools
l = more_itertools.chunked(range(1,10), 3)
r = more_itertools.unzip(l) # a tuple of generators.
r = list(map(list, r))      # a list of lists

-1

必ずしも正方形ではないリストのリストを転置するためのソリューションは次のとおりです。

maxCol = len(l[0])
for row in l:
    rowLength = len(row)
    if rowLength > maxCol:
        maxCol = rowLength
lTrans = []
for colIndex in range(maxCol):
    lTrans.append([])
    for row in l:
        if colIndex < len(row):
            lTrans[colIndex].append(row[colIndex])

-2
    #Import functions from library
    from numpy import size, array
    #Transpose a 2D list
    def transpose_list_2d(list_in_mat):
        list_out_mat = []
        array_in_mat = array(list_in_mat)
        array_out_mat = array_in_mat.T
        nb_lines = size(array_out_mat, 0)
        for i_line_out in range(0, nb_lines):
            array_out_line = array_out_mat[i_line_out]
            list_out_line = list(array_out_line)
            list_out_mat.append(list_out_line)
        return list_out_mat
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.