「タプルのリスト」をフラットリストまたはマトリックスに変換します


82

Sqliteを使用すると、「select..from」コマンドは結果「output」を返し、次のように出力します(Pythonの場合)。

>>print output
[(12.2817, 12.2817), (0, 0), (8.52, 8.52)]

タプルのリストのようです。単純な1D配列(= Pythonのリスト)に「出力」を変換したいと思います。

[12.2817, 12.2817, 0, 0, 8.52, 8.52]

または2x3マトリックス:

12.2817 12.2817
0          0 
8.52     8.52

「output [i] [j]」を介して読み取られます

flattenコマンドは、最初のオプションでは機能しません。2番目のオプションについてはわかりません... :)

ヒントを教えてください。実際のデータははるかに大きいので、高速なものがあれば素晴らしいでしょう(これは単純な例です)。


2
[(12.2817, 12.2817), (0, 0), (8.52, 8.52)]すでに3x2行列です!?または私は何かを逃しましたか?
mouad 2012年


1
flatten関数チェックitertoolsモジュールレシピについては、既にflatten関数の例があります:docs.python.org/library/itertools.html#recipes
mouad

4
[item for sublist in output for item in sublist]完全に機能し、内側のタプルもリストになる可能性があるという利点があります。より一般的には、内側と外側の反復可能な作品の任意の組み合わせ
Kyss Tao 2013

回答:


125

投稿された最も速い(そして最も短い)ソリューション:

list(sum(output, ()))

itertoolsソリューションよりも約50%速く、ソリューションよりも約70%高速ですmap


8
@ジョエルいいけど、どうやって動くのかな?list(output[0]+output[1]+output[2])望ましい結果が得られますが、得られlist(sum(output))ません。どうして?()はどのような「魔法」を実行しますか?
Kyss Tao 2013

9
わかりました、私はマニュアルgを読むべきでした。どうやらsum(sequence[, start]):sumは、存在する場合から開始して残りの要素を追加するのではなく、startデフォルトで追加します。お邪魔になってすみません。0sequence[0]
Kyss Tao 2013

3
これはよく知られているアンチパターンです。sumシーケンスを連結するために使用しないでください。2次時間アルゴリズムになります。確かに、sum文字列でこれを行おうとすると、関数は文句を言います!
juanpa.arrivillaga 2018

@ juanpa.arrivillaga:同意しました。これが望ましいユースケースはほとんどありません。
Joel Cornett 2018

9
はい、速いですが完全に鈍いです。あなたはそれが実際に何をしているのかについてコメントを残さなければならないでしょう:(
CpILL 2018年

42

Iterableタイプで機能し、ここに示されている他の方法よりも高速なリスト内包法。

flattened = [item for sublist in l for item in sublist]

l平坦化するリストです(outputOPの場合に呼び出されます)


timeitテスト:

l = list(zip(range(99), range(99)))  # list of tuples to flatten

リスト内包

[item for sublist in l for item in sublist]

timeitの結果= 7.67 µs±129 ns /ループ

リストextend()メソッド

flattened = []
list(flattened.extend(item) for item in l)

timeitの結果= 11 µs±433 ns /ループ

和()

list(sum(l, ()))

timeitの結果= 24.2 µs±269 ns /ループ


1
大規模なデータセットでこれを使用する必要がありました。リスト内包法がはるかに高速でした。
nbeuchat 2018

.extendソリューションに少し変更を加えたところ、パフォーマンスが少し向上しました。比較するためにあなたのtimeitでそれをチェックしてください
トトロ

24

Python 2.7およびPython3のすべてのバージョンでは、を使用itertools.chainして反復可能オブジェクトのリストをフラット化できます。*構文またはクラスメソッドのいずれかを使用します。

>>> t = [ (1,2), (3,4), (5,6) ]
>>> t
[(1, 2), (3, 4), (5, 6)]
>>> import itertools
>>> list(itertools.chain(*t))
[1, 2, 3, 4, 5, 6]
>>> list(itertools.chain.from_iterable(t))
[1, 2, 3, 4, 5, 6]

11

更新:extendを使用してフラット化するが、理解せず、リストをイテレーターとして使用しない(最速)

これに対する次の答えを確認した後、リスト内包表記を介してより高速なソリューションを提供しましたdual forが、少し調整しましたが、パフォーマンスが向上しました。最初にlist(...)を実行すると、かなりの時間がドラッグされ、次にリストが変更されました。単純なループの理解も少し削られました。

新しいソリューションは次のとおりです。

l = []
for row in output: l.extend(row)

古い:

マップ/拡張によるフラット化:

l = []
list(map(l.extend, output))

マップの代わりにリスト内包を使用したフラット化

l = []
list(l.extend(row) for row in output)

[...]のlist(...)を削除するだけで、新しい拡張と改善のためのいくつかの時間が得られます。

import timeit
t = timeit.timeit
o = "output=list(zip(range(1000000000), range(10000000))); l=[]"
steps_ext = "for row in output: l.extend(row)"
steps_ext_old = "list(l.extend(row) for row in output)"
steps_ext_remove_list = "[l.extend(row) for row in output]"
steps_com = "[item for sublist in output for item in sublist]"

print("new extend:      ", t(steps_ext, setup=o, number=10))
print("old extend w []: ", t(steps_ext_remove_list, setup=o, number=10))
print("comprehension:   ", t(steps_com, setup=o, number=10,))
print("old extend:      ", t(steps_ext_old, setup=o, number=10))

>>> new extend:       4.502427191007882
>>> old extend w []:  5.281140706967562
>>> comprehension:    5.54302118299529
>>> old extend:       6.840151469223201    

9

itertoolsチェーンの使用:

>>> import itertools
>>> list(itertools.chain.from_iterable([(12.2817, 12.2817), (0, 0), (8.52, 8.52)]))
[12.2817, 12.2817, 0, 0, 8.52, 8.52]

7
>>> flat_list = []
>>> nested_list = [(1, 2, 4), (0, 9)]
>>> for a_tuple in nested_list:
...     flat_list.extend(list(a_tuple))
... 
>>> flat_list
[1, 2, 4, 0, 9]
>>> 

上記のように、タプルのリストから単一のリストに簡単に移動できます。


7

または、次のようにリストをフラット化できます。

reduce(lambda x,y:x+y, map(list, output))

reduce(lambda x,y:x+y, output)長いタプル(リストに変換できます)に直接変換すると機能するようです。なぜ通話map(list, output)内で使用するのreduce()ですか?多分それはタプルが不変であり、リストが可変であるという事実とより一致しています
PaulRougieux19年

5

これはnumpy、データ構造と速度の両方の観点から作成されたものです。

import numpy as np

output = [(12.2817, 12.2817), (0, 0), (8.52, 8.52)]
output_ary = np.array(output)   # this is your matrix 
output_vec = output_ary.ravel() # this is your 1d-array

2

任意のネストされたリストの場合(念のため):

def flatten(lst):
    result = []
    for element in lst: 
        if hasattr(element, '__iter__'):
            result.extend(flatten(element))
        else:
            result.append(element)
    return result

>>> flatten(output)
[12.2817, 12.2817, 0, 0, 8.52, 8.52]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.