94

使用 Sqlite,一个select .. from命令会返回 results output,它会打印:

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

它似乎是一个元组列表。我想转换output为一个简单的列表:

[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 命令对第一个选项不起作用,我不知道第二个选项...

一个快速的解决方案将不胜感激,因为真实数据要大得多。

4

10 回答 10

144

迄今为止发布的最快(和最短)的解决方案:

list(sum(output, ()))

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

于 2012-05-17T13:22:37.990 回答
60

列表理解方法适用于 Iterable 类型,并且比此处显示的其他方法更快。

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

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


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 每个循环

列表扩展()方法

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

timeit 结果 = 11 µs ± 433 ns 每个循环

和()

list(sum(l, ()))

timeit 结果 = 24.2 µs ± 269 ns 每个循环

于 2018-07-11T17:14:29.553 回答
29

在 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]
于 2016-02-05T16:01:34.960 回答
16

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

在检查了通过列表理解提供更快解决方案的下一个答案之后,dual for我做了一些调整,现在它表现更好,首先执行 list(...) 拖了很大一部分时间,然后更改了列表对简单循环的理解也减少了一点。

新的解决方案是:

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

旧的替换list[](有点慢但不多):

[l.extend(row) for row in 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(f"{steps_ext}\n>>>{t(steps_ext, setup=o, number=10)}")
print(f"{steps_ext_remove_list}\n>>>{t(steps_ext_remove_list, setup=o, number=10)}")
print(f"{steps_com}\n>>>{t(steps_com, setup=o, number=10)}")
print(f"{steps_ext_old}\n>>>{t(steps_ext_old, setup=o, number=10)}")

结果的时间:

for row in output: l.extend(row)                  
>>> 7.022608777000187

[l.extend(row) for row in output]
>>> 9.155910597999991

[item for sublist in output for item in sublist]
>>> 9.920002304000036

list(l.extend(row) for row in output)
>>> 10.703829122000116
于 2017-09-13T15:10:18.933 回答
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]
于 2012-05-17T11:10:39.833 回答
9
>>> 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]
>>> 

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

于 2012-05-17T09:36:20.547 回答
7

或者您可以像这样展平列表:

reduce(lambda x,y:x+y, map(list, output))
于 2012-05-17T11:05:38.370 回答
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
于 2018-09-20T16:10:30.947 回答
3

如果是任意嵌套列表(以防万一):

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]
于 2012-05-17T10:03:21.833 回答
3
def flatten_tuple_list(tuples):
    return list(sum(tuples, ()))


tuples = [(5, 6), (6, 7, 8, 9), (3,)]
print(flatten_tuple_list(tuples))
于 2021-02-05T16:58:54.730 回答