web-dev-qa-db-fra.com

Tête et queue en une ligne

Existe-t-il un moyen Pythonic pour décompresser une liste dans le premier élément et le "tail" dans une seule commande?

Par exemple:

>> head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
81

Sous Python 3.x, vous pouvez le faire facilement:

>>> head, *tail = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]

Une nouvelle fonctionnalité de la version 3.x consiste à utiliser l'opérateur * Lors de la décompression, pour indiquer les valeurs supplémentaires. Il est décrit dans PEP 3132 - Décompression itérative étendue . Cela présente également l’avantage de travailler sur n’importe quelle séquence, mais uniquement sur des séquences.

C'est aussi vraiment lisible.

Comme décrit dans le PEP, si vous souhaitez effectuer l'équivalent sous 2.x (sans potentiellement créer une liste temporaire), vous devez procéder comme suit:

it = iter(iterable)
head, tail = next(it), list(it)

Comme indiqué dans les commentaires, cela permet également d’obtenir une valeur par défaut pour head plutôt que de générer une exception. Si vous voulez ce comportement, next() prend un second argument optionnel avec une valeur par défaut, donc next(it, None) vous donnerait None s'il y avait pas d'élément de tête.

Naturellement, si vous travaillez sur une liste, le moyen le plus simple de ne pas utiliser la syntaxe 3.x est:

head, tail = seq[0], seq[1:]
173
Gareth Latty
>>> mylist = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> head, tail = mylist[0], mylist[1:]
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
35
fraxel

Pour O(1) complexité de head,tail opération vous devez utiliser deque cependant.

Manière suivante:

from collections import deque
l = deque([1,2,3,4,5,6,7,8,9])
head, tail = l.popleft(), l

C'est utile lorsque vous devez parcourir tous les éléments de la liste. Par exemple, dans la fusion naïve de 2 partitions en fusion.

8
Nikolay Fominyh

Python 2, en utilisant lambda

>>> head, tail = (lambda lst: (lst[0], lst[1:]))([1, 1, 2, 3, 5, 8, 13, 21, 34, 55])
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
2
BobIsNotMyName

En vous basant sur la solution Python 2 de @GarethLatty , voici un moyen d’obtenir un équivalent simple ligne sans variables intermédiaires dans Python 2.

t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]

Si vous avez besoin que ce soit à l'épreuve des exceptions (c'est-à-dire une liste vide supportée), ajoutez:

t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]

Si vous voulez le faire sans le point-virgule, utilisez:

h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]
1
ABridgeTooFar