Comment convertir un tuple de tuples en liste unidimensionnelle en utilisant la compréhension de liste? [dupliquer]
cette question a déjà une réponse ici:
j'ai un tuple de tuples-par exemple:
tupleOfTuples = ((1, 2), (3, 4), (5,))
je veux transformer ceci en une liste plate, unidimensionnelle de tous les les éléments dans l'ordre:
[1, 2, 3, 4, 5]
j'ai essayé d'accomplir ceci avec la compréhension de liste. Mais je n'arrive pas à le comprendre. J'ai pu l'accomplir avec une boucle pour chaque boucle:
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 liste.
simple [list(tuple) for tuple in tupleOfTuples]
vous donne une liste de listes, au lieu d'éléments individuels. J'ai pensé que je pourrais peut-être construire sur ce en utilisant le opérateur de déballage pour ensuite déballer la liste, comme ceci:
[*list(tuple) for tuple in tupleOfTuples]
ou
[*(list(tuple)) for tuple in tupleOfTuples]
... mais cela ne fonctionne pas. Des idées? Ou devrais-je m'en tenir à la boucle?
7 réponses
on appelle ça aplatir une structure emboîté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 : S'il vous plaît n'utilisez pas tuple
comme nom variable, il ombrage intégré.
il suffit d'utiliser 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 liste de compréhension ou chain.from_iterable
pour prévenir le comportement quadratique de sum
.
Micro-benchmarks:
-
Python 2.6
-
Long tuple de court 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
-
Court tuple de 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 n-uplet de court 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
-
Court tuple de 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
est plus rapide si le tuple extérieur est court. -
list(chain.from_iterable(x))
est plus rapide si le tuple extérieur est long.
Vous êtes le chaînage de l'ensemble des n-uplets:
from itertools import chain
print list(chain(*listOfTuples))
devrait être assez lisible si vous êtes familier avec 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 (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 "réduire" dans cette situation (c'est ce que réduire la!)
lot = ((1, 2), (3, 4), (5,))
print list(reduce(lambda t1, t2: t1 + t2, lot))
> [1,2,3,4,5]
pour le multilevel, et le code 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 obtenir ce pour tenir dans une seule ligne (et restent lisibles, même de loin)
une autre solution utilisant itértools.chaîne
>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> from itertools import chain
>>> [x for x in chain.from_iterable(tupleOfTuples)]
[1, 2, 3, 4, 5]