将“元组列表”转换为平面列表或矩阵


82

使用Sqlite时,“ select..from”命令返回结果“输出”,该结果打印(在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
[(12.2817, 12.2817), (0, 0), (8.52, 8.52)]已经是3x2矩阵!还是我错过了什么?
2012年


1

4
[item for sublist in output for item in sublist]工作完美,并具有内部元组也可以是列表的优点;更普遍的是,内部和外部可迭代作品的任何组合
陶凯茜(Kyss Tao)

Answers:


125

迄今为止最快(也是最短)的解决方案:

list(sum(output, ()))

itertools解决方案快约50%,比解决方案快约70%map


8
@Joel很好,但我想知道它是如何工作的?list(output[0]+output[1]+output[2])给出期望的结果,但list(sum(output))没有。为什么?()的作用是什么?
陶凯丝

9
好的,我应该已经阅读了手册g。似乎sum(sequence[, start]):sum添加了start默认值,0而不是从sequence[0]它是否存在开始,然后添加其余元素。对不起,打扰你。
陶凯丝

3
这是一个众所周知的反模式:不用于sum连接序列,它会产生二次时间算法。的确,sum如果您尝试使用字符串执行此功能,该函数将发出抱怨!
juanpa.arrivillaga

@ juanpa.arrivillaga:同意。很少有用例会更可取。
乔尔·科内特

9
是的,很快但完全钝了。您必须对它的实际作用发表评论:(
CpILL

42

列表理解方法可与Iterable类型一起使用,并且比此处显示的其他方法更快。

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

l是要展平的列表(output在OP的情况下称为)


定时测试:

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

我对.extend解决方案进行了一些更改,现在性能有所提高。在您的时间上进行检查以进行比较
龙猫

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

更新:使用扩展但不理解且不使用列表作为迭代器进行展平(最快)

在检查了下一个答案之后,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]
>>> 

您可以轻松地从元组列表移动到单个列表,如上所示。



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]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.