J'ai un tuple de tuples - par exemple:
tupleOfTuples = ((1, 2), (3, 4), (5,))
Je veux convertir cela en une liste plate et unidimensionnelle de tous les éléments dans l'ordre:
[1, 2, 3, 4, 5]
J'ai essayé d'accomplir cela avec une compréhension de la liste. Mais je n'arrive pas à comprendre. J'ai pu l'accomplir avec une boucle pour chaque:
myList = []
for Tuple in tupleOfTuples:
myList = myList + list(Tuple)
Mais je pense qu'il doit y avoir un moyen de le faire avec une compréhension de la liste.
Une simple [list(Tuple) for Tuple in tupleOfTuples]
vous donne simplement une liste de listes, au lieu d'éléments individuels. J'ai pensé que je pourrais peut-être m'appuyer sur cela en utilisant l'opérateur de déballage pour ensuite décompresser la liste, comme ceci:
[*list(Tuple) for Tuple in tupleOfTuples]
ou
[*(list(Tuple)) for Tuple in tupleOfTuples]
... mais cela n'a pas fonctionné. Des idées? Ou devrais-je simplement m'en tenir à la boucle?
il s'agit généralement d'aplatir une structure imbriquée.
>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> [element for tupl in tupleOfTuples for element in tupl]
[1, 2, 3, 4, 5]
Juste pour démontrer l'efficacité:
>>> 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 : Veuillez ne pas utiliser Tuple
comme nom de variable, il crée des ombres intégrées.
Utilisez simplement sum
si vous n'avez pas beaucoup de tuples.
>>> 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]
Si vous avez beaucoup de tuples, utilisez compréhension de liste ou chain.from_iterable
pour empêcher le comportement quadratique de sum
.
Python 2.6
Tuple long de tuples courts
$ 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
Tuple court de tuples longs
$ 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
Tuple long de tuples courts
$ 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
Tuple court de tuples longs
$ 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
est plus rapide si le Tuple externe est court.list(chain.from_iterable(x))
est plus rapide si le Tuple externe est long.Vous enchaînez les tuples ensemble:
from itertools import chain
print list(chain(*listOfTuples))
Devrait être assez lisible si vous connaissez itertools
, et sans le list
explicite, vous avez même votre résultat sous forme de générateur.
La plupart de ces réponses ne fonctionneront que pour un seul niveau d'aplatissement. Pour une solution plus complète, essayez ceci (à partir de 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)
J'aime utiliser 'réduire' dans cette situation (c'est pour ça que réduire est fait!)
lot = ((1, 2), (3, 4), (5,))
print list(reduce(lambda t1, t2: t1 + t2, lot))
> [1,2,3,4,5]
Pour un code à plusieurs niveaux et lisible:
def flatten(bla):
output = []
for item in bla:
output += flatten(item) if hasattr (item, "__iter__") or hasattr (item, "__len__") else [item]
return output
Je ne pouvais pas faire tenir cela sur une seule ligne (et rester lisible, même de loin)
Une autre solution utilisant 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]