Чи існує пітонічний спосіб розпакувати список у першому елементі та "хвіст" за допомогою однієї команди?
Наприклад:
>> 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]
Чи існує пітонічний спосіб розпакувати список у першому елементі та "хвіст" за допомогою однієї команди?
Наприклад:
>> 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]
Відповіді:
Під Python 3.x ви можете зробити це чудово:
>>> head, *tail = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
Нова функція в 3.x полягає у використанні *
оператора при розпаковуванні, що означає будь-які зайві значення. Це описано в PEP 3132 - Розширене розпаковування, що підлягає ітерації . Це також має перевагу в роботі над будь-якими ітераційними, а не лише послідовностями.
Це також справді читається.
Як описано в PEP, якщо ви хочете зробити еквівалент під 2.x (без потенційного складання тимчасового списку), вам потрібно зробити це:
it = iter(iterable)
head, tail = next(it), list(it)
Як зазначалося у коментарях, це також надає можливість отримати значення за замовчуванням, head
а не викидати виняток. Якщо ви хочете такої поведінки, next()
приймає необов'язковий другий аргумент зі значенням за замовчуванням, тому next(it, None)
дасть вам, None
якщо не було елемента head.
Звичайно, якщо ви працюєте над списком, найпростіший спосіб без синтаксису 3.x:
head, tail = seq[0], seq[1:]
__getitem__
/ __setitem__
виконувати операцію хвоста ліниво, але вбудований список цього не робить.
python 3.x
Однак для складності head,tail
операції O (1) вам слід скористатися deque
.
Наступним способом:
from collections import deque
l = deque([1,2,3,4,5,6,7,8,9])
head, tail = l.popleft(), l
Це корисно, коли ви повинні переглядати всі елементи списку. Наприклад, при наївному об'єднанні 2 розділів у режимі сортування.
head, tail = l.popleft(), l
це ~ O (1). head, tail = seq[0], seq[1:]
дорівнює O (n).
head = l.popleft()
і tail
є просто псевдонімом для l
. Якщо l
зміни tail
зміни теж.
Python 2, використовуючи лямбду
>>> 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]
head, tail = lst[0], lst[1:]
? якщо ОП означає використовувати літерал, тоді він міг би розділити голову та хвіст вручнуhead, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
lst = ...
в попередньому рядку). (2) Doing head, tail = lst[0], lst[1:]
залишає код відкритим для побічних ефектів (розглянемо head, tail = get_list()[0], get_list()[1:]
) і відрізняється від форми Op head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
.
Спираючись на рішення Python 2 від @GarethLatty , далі наведено спосіб отримати однорядковий еквівалент без проміжних змінних у Python 2.
t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]
Якщо вам потрібно, щоб він був захищений від винятків (тобто підтримував порожній список), додайте:
t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]
Якщо ви хочете зробити це без крапки з комою, використовуйте:
h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]