如何使用列表推导将元组的元组转换为一维列表?
我有一个包含元组的元组,比如说:
tupleOfTuples = ((1, 2), (3, 4), (5,))
我想把它转换成一个扁平的一维列表,里面包含所有的元素,顺序也要对:
[1, 2, 3, 4, 5]
我一直在尝试用列表推导式来实现这个目标,但我总是搞不定。其实我用循环是可以做到的:
myList = []
for tuple in tupleOfTuples:
myList = myList + list(tuple)
不过我觉得应该有办法用列表推导式来完成这个。
简单的写法 [list(tuple) for tuple in tupleOfTuples]
只会给我一个列表的列表,而不是单独的元素。我想也许可以用解包操作符来解包这个列表,像这样:
[*list(tuple) for tuple in tupleOfTuples]
或者
[*(list(tuple)) for tuple in tupleOfTuples]
...但这样也不行。有什么想法吗?还是我就继续用循环吧?
7 个回答
13
你正在把元组连接在一起:
from itertools import chain
print list(chain(*listOfTuples))
如果你对 itertools
有点了解,这段代码应该挺容易理解的。而且如果不使用明确的 list
,你得到的结果还是生成器的形式。
46
如果你的元组不多,就直接用 sum
吧。
>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> sum(tupleOfTuples, ())
(1, 2, 3, 4, 5)
>>> list(sum(tupleOfTuples, ())) # if you really need a list
[1, 2, 3, 4, 5]
如果你的元组很多,那就用列表推导式或者chain.from_iterable
,这样可以避免 sum
的性能问题。
微基准测试:
Python 2.6
长元组包含短元组
$ python2.6 -m timeit -s 'tot = ((1, 2), )*500' '[element for tupl in tot for element in tupl]' 10000 loops, best of 3: 134 usec per loop $ python2.6 -m timeit -s 'tot = ((1, 2), )*500' 'list(sum(tot, ()))' 1000 loops, best of 3: 1.1 msec per loop $ python2.6 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain; ci = chain.from_iterable' 'list(ci(tot))' 10000 loops, best of 3: 60.1 usec per loop $ python2.6 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain' 'list(chain(*tot))' 10000 loops, best of 3: 64.8 usec per loop
短元组包含长元组
$ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500)' '[element for tupl in tot for element in tupl]' 10000 loops, best of 3: 65.6 usec per loop $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500)' 'list(sum(tot, ()))' 100000 loops, best of 3: 16.9 usec per loop $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain; ci = chain.from_iterable' 'list(ci(tot))' 10000 loops, best of 3: 25.8 usec per loop $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain' 'list(chain(*tot))' 10000 loops, best of 3: 26.5 usec per loop
Python 3.1
长元组包含短元组
$ python3.1 -m timeit -s 'tot = ((1, 2), )*500' '[element for tupl in tot for element in tupl]' 10000 loops, best of 3: 121 usec per loop $ python3.1 -m timeit -s 'tot = ((1, 2), )*500' 'list(sum(tot, ()))' 1000 loops, best of 3: 1.09 msec per loop $ python3.1 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain; ci = chain.from_iterable' 'list(ci(tot))' 10000 loops, best of 3: 59.5 usec per loop $ python3.1 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain' 'list(chain(*tot))' 10000 loops, best of 3: 63.2 usec per loop
短元组包含长元组
$ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500)' '[element for tupl in tot for element in tupl]' 10000 loops, best of 3: 66.1 usec per loop $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500)' 'list(sum(tot, ()))' 100000 loops, best of 3: 16.3 usec per loop $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain; ci = chain.from_iterable' 'list(ci(tot))' 10000 loops, best of 3: 25.4 usec per loop $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain' 'list(chain(*tot))' 10000 loops, best of 3: 25.6 usec per loop
观察结果:
- 如果外层元组很短,
sum
会更快。 - 如果外层元组很长,
list(chain.from_iterable(x))
会更快。
76
这通常被称为“扁平化嵌套结构”。
>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> [element for tupl in tupleOfTuples for element in tupl]
[1, 2, 3, 4, 5]
只是为了展示效率:
>>> import timeit
>>> it = lambda: list(chain(*tupleOfTuples))
>>> timeit.timeit(it)
2.1475738355700913
>>> lc = lambda: [element for tupl in tupleOfTuples for element in tupl]
>>> timeit.timeit(lc)
1.5745135182887857
注意: 请不要把 tuple
用作变量名,这样会覆盖掉内置的功能。