Doublons Possibles:
Mise à plat d'un peu profond liste en Python
La compréhension de l'aplatissement d'une séquence de séquences?Je me demande si il existe un raccourci pour faire une simple liste de liste de listes en Python.
Je peux le faire dans une boucle for, mais peut-être qu'il est cool "one-liner"? Je l'ai essayé avec de la réduire, mais j'obtiens une erreur.
Code
l = [[1,2,3],[4,5,6], [7], [8,9]] reduce(lambda x,y: x.extend(y),l)
Message d'erreur
Traceback (most recent call last): File "", line 1, in File "", line 1, in AttributeError: 'NoneType' object n'a pas d'attribut "prolonger"
Réponses
Trop de publicités?[item for sublist in l for item in sublist]
est plus rapide que les raccourcis affichés jusqu'à présent.
Pour preuve, comme toujours, vous pouvez utiliser l' timeit
module de la bibliothèque standard:
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop
Explication: les raccourcis basés sur +
(y compris l'implicite d'utilisation en sum
) sont, de toute nécessité, O(L**2)
quand il y a L des sous-listes -- comme le résultat intermédiaire de la liste ne cesse de s'allonger, à chaque étape un nouveau résultat intermédiaire des objets de la liste de paie, et tous les éléments dans le précédent résultat intermédiaire doit être copié (ainsi que quelques nouveaux ajoutés à la fin). (Pour des raisons de simplicité et sans perte de généralité) que vous avez L des sous-listes de I éléments chacune: la première fois que je les éléments sont copiés en arrière L-1 fois, la seconde, j'ai des éléments de L-2 fois, et ainsi de suite; le nombre total de copies est je fois la somme de x pour x de 1 à L exclu, c'est à dire, I * (L**2)/2
.
La compréhension de liste génère une liste, une fois, et de copies de chaque élément de plus (l'original de son lieu de résidence à la liste des résultats) aussi exactement une fois.
Vous pouvez utiliser itertools.chain()
:
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))
ou, sur Python >=2.6, utilisez itertools.chain.from_iterable()
qui ne nécessite pas de déballage de la liste:
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))
Cette approche est sans doute plus lisible qu' [item for sublist in l for item in sublist]
et semble être plus rapide aussi:
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
10000 loops, best of 3: 24.2 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 45.2 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 488 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 522 usec per loop
[me@home]$ python --version
Python 2.7.3