This question already has an answer here:
这个问题在这里已有答案:
- Flattening a shallow list in Python [duplicate] 23 answers
在Python中展平浅表[重复] 23个答案
I have a tuple of tuples - for example:
我有一个元组元组 - 例如:
tupleOfTuples = ((1, 2), (3, 4), (5,))
I want to convert this into a flat, one-dimensional list of all the elements in order:
我想按顺序将其转换为所有元素的平面一维列表:
[1, 2, 3, 4, 5]
I've been trying to accomplish this with list comprehension. But I can't seem to figure it out. I was able to accomplish it with a for-each loop:
我一直试图通过列表理解来实现这一目标。但我似乎无法弄明白。我能够通过for-each循环完成它:
myList = []
for tuple in tupleOfTuples:
myList = myList + list(tuple)
But I feel like there must be a way to do this with a list comprehension.
但我觉得必须有一种方法可以通过列表理解来做到这一点。
A simple [list(tuple) for tuple in tupleOfTuples]
just gives you a list of lists, instead of individual elements. I thought I could perhaps build on this by using the unpacking operator to then unpack the list, like so:
一个简单的[tupleOfTuples中元组的列表(元组)]只给出一个列表列表,而不是单个元素。我想我可以通过使用解包操作符然后解压缩列表来构建它,如下所示:
[*list(tuple) for tuple in tupleOfTuples]
or
[*(list(tuple)) for tuple in tupleOfTuples]
... but that didn't work. Any ideas? Or should I just stick to the loop?
......但那没用。有任何想法吗?或者我应该坚持循环?
7 个解决方案
#1
54
it's typically referred to as flattening a nested structure.
它通常被称为展平嵌套结构。
>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> [element for tupl in tupleOfTuples for element in tupl]
[1, 2, 3, 4, 5]
Just to demonstrate efficiency:
只是为了证明效率:
>>> 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
ETA: Please don't use tuple
as a variable name, it shadows built-in.
ETA:请不要使用元组作为变量名,它会内置阴影。
#2
32
Just use sum
if you don't have a lot of tuples.
如果你没有很多元组,只需使用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]
If you do have a lot of tuples, use list comprehension or chain.from_iterable
to prevent the quadratic behavior of sum
.
如果你确实有很多元组,请使用list comprehension或chain.from_iterable来防止sum的二次行为。
Micro-benchmarks:
-
Python 2.6
-
Long tuple of short tuples
长元组的短元组
$ 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
-
Short tuple of long tuples
长元组的短元组
$ 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
-
Long tuple of short tuples
长元组的短元组
$ 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
-
Short tuple of long tuples
长元组的短元组
$ 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
-
Observation:
-
sum
is faster if the outer tuple is short. -
list(chain.from_iterable(x))
is faster if the outer tuple is long.
如果外元组很短,则总和更快。
如果外部元组很长,list(chain.from_iterable(x))会更快。
#3
8
You're chaining the tuples together:
你把元组连在一起:
from itertools import chain
print list(chain(*listOfTuples))
Should be pretty readable if you're familiar with itertools
, and without the explicit list
you even have your result in generator form.
如果您熟悉itertools,那么应该是非常易读的,如果没有明确的列表,您甚至可以以生成器形式获得结果。
#4
7
Most of these answers will only work for a single level of flattening. For a more comprehensive solution, try this (from http://rightfootin.blogspot.com/2006/09/more-on-python-flatten.html):
大多数答案只适用于单一的扁平化。有关更全面的解决方案,请尝试此操作(来自http://rightfootin.blogspot.com/2006/09/more-on-python-flatten.html):
def flatten(l, ltypes=(list, tuple)):
ltype = type(l)
l = list(l)
i = 0
while i < len(l):
while isinstance(l[i], ltypes):
if not l[i]:
l.pop(i)
i -= 1
break
else:
l[i:i + 1] = l[i]
i += 1
return ltype(l)
#5
6
I like using 'reduce' in this situation (this is what reduce made for!)
我喜欢在这种情况下使用'reduce'(这是减少的!)
lot = ((1, 2), (3, 4), (5,))
print list(reduce(lambda t1, t2: t1 + t2, lot))
> [1,2,3,4,5]
#6
4
For multilevel, and readable code:
对于多级可读代码:
def flatten(bla):
output = []
for item in bla:
output += flatten(item) if hasattr (item, "__iter__") or hasattr (item, "__len__") else [item]
return output
I could not get this to fit in one line (and remain readable, even by far)
我不能让它适合一行(并且仍然可读,即使到目前为止)
#7
1
Another solution using itertools.chain
另一种使用itertools.chain的解决方案
>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> from itertools import chain
>>> [x for x in chain.from_iterable(tupleOfTuples)]
[1, 2, 3, 4, 5]
#1
54
it's typically referred to as flattening a nested structure.
它通常被称为展平嵌套结构。
>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> [element for tupl in tupleOfTuples for element in tupl]
[1, 2, 3, 4, 5]
Just to demonstrate efficiency:
只是为了证明效率:
>>> 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
ETA: Please don't use tuple
as a variable name, it shadows built-in.
ETA:请不要使用元组作为变量名,它会内置阴影。
#2
32
Just use sum
if you don't have a lot of tuples.
如果你没有很多元组,只需使用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]
If you do have a lot of tuples, use list comprehension or chain.from_iterable
to prevent the quadratic behavior of sum
.
如果你确实有很多元组,请使用list comprehension或chain.from_iterable来防止sum的二次行为。
Micro-benchmarks:
-
Python 2.6
-
Long tuple of short tuples
长元组的短元组
$ 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
-
Short tuple of long tuples
长元组的短元组
$ 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
-
Long tuple of short tuples
长元组的短元组
$ 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
-
Short tuple of long tuples
长元组的短元组
$ 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
-
Observation:
-
sum
is faster if the outer tuple is short. -
list(chain.from_iterable(x))
is faster if the outer tuple is long.
如果外元组很短,则总和更快。
如果外部元组很长,list(chain.from_iterable(x))会更快。
#3
8
You're chaining the tuples together:
你把元组连在一起:
from itertools import chain
print list(chain(*listOfTuples))
Should be pretty readable if you're familiar with itertools
, and without the explicit list
you even have your result in generator form.
如果您熟悉itertools,那么应该是非常易读的,如果没有明确的列表,您甚至可以以生成器形式获得结果。
#4
7
Most of these answers will only work for a single level of flattening. For a more comprehensive solution, try this (from http://rightfootin.blogspot.com/2006/09/more-on-python-flatten.html):
大多数答案只适用于单一的扁平化。有关更全面的解决方案,请尝试此操作(来自http://rightfootin.blogspot.com/2006/09/more-on-python-flatten.html):
def flatten(l, ltypes=(list, tuple)):
ltype = type(l)
l = list(l)
i = 0
while i < len(l):
while isinstance(l[i], ltypes):
if not l[i]:
l.pop(i)
i -= 1
break
else:
l[i:i + 1] = l[i]
i += 1
return ltype(l)
#5
6
I like using 'reduce' in this situation (this is what reduce made for!)
我喜欢在这种情况下使用'reduce'(这是减少的!)
lot = ((1, 2), (3, 4), (5,))
print list(reduce(lambda t1, t2: t1 + t2, lot))
> [1,2,3,4,5]
#6
4
For multilevel, and readable code:
对于多级可读代码:
def flatten(bla):
output = []
for item in bla:
output += flatten(item) if hasattr (item, "__iter__") or hasattr (item, "__len__") else [item]
return output
I could not get this to fit in one line (and remain readable, even by far)
我不能让它适合一行(并且仍然可读,即使到目前为止)
#7
1
Another solution using itertools.chain
另一种使用itertools.chain的解决方案
>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> from itertools import chain
>>> [x for x in chain.from_iterable(tupleOfTuples)]
[1, 2, 3, 4, 5]