한 줄의 머리와 꼬리


91

단일 명령으로 첫 번째 요소의 목록과 "꼬리"의 압축을 푸는 파이썬적인 방법이 있습니까?

예를 들면 :

>> 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]

9
목록은 Python에서 단일 연결 목록으로 구현되지 않으므로이 작업은 비용이 많이 듭니다 (예 : 전체 목록을 복사해야 함). 달성하고자하는 것에 따라 이것은 문제가 될 수도 있고 아닐 수도 있습니다. 이러한 유형의 목록 분해는 함수 언어에서 종종 발견되기 때문에 실제로 매우 저렴한 작업이라는 점을 언급하고 있습니다.
Niklas B.

답변:


191

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-Extended Iterable Unpacking에 설명되어 있습니다. 또한 시퀀스뿐만 아니라 반복 가능한 모든 작업을 수행 할 수있는 이점이 있습니다.

또한 정말 읽기 쉽습니다.

PEP에 설명 된대로 2.x에서 (잠재적으로 임시 목록을 만들지 않고) 동등한 작업을 수행하려면 다음을 수행해야합니다.

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

주석에서 언급했듯이 이것은 head예외를 던지는 대신 기본값을 얻을 수있는 기회를 제공합니다 . 이 동작을 원하면 next()기본값이있는 선택적 두 번째 인수를 사용하므로 헤드 요소가없는 경우 next(it, None)제공합니다 None.

당연히 목록에서 작업하는 경우 3.x 구문이없는 가장 쉬운 방법은 다음과 같습니다.

head, tail = seq[0], seq[1:]

1
죄송합니다. 꼬리라는 용어를 잘못 사용했습니다. 제 말은 제가 예에서 말한 것입니다. 그것은 첫 번째 요소가없는 목록입니다
Giacomo d' Antonio

1
@NikolayFominyh 둘 다 동일합니다. 둘 다 head 요소를 취하고 tail 요소를 포함하는 새 목록을 구성합니다. 복잡성에 차이가 없습니다. 또 다른 클래스를 구현할 수 __getitem__/ __setitem__느리게 꼬리 작업을 할 수 있지만, 내장 된 목록은하지 않습니다.
가레스 Latty

2
1M 번 수행하는 800 개의 요소 목록에서 머리에 2.8 초, * 꼬리 = seq 솔루션, 머리에 1.8 초, 꼬리 = seq [0], seq [1 :] 솔루션이 있습니다. 목록의 경우 슬라이싱이 더 빠릅니다.
Cabu

2
@CMCDragonkai 아니요, Python의 기본 목록 클래스는 배열 목록입니다. 꼬리를 새 목록에 복사하는 것이 포함되므로 O (n)이됩니다 (머리에 하나의 O (1) 가져 오기).
가레스 Latty

1
이 좋은 구문으로 이동하는 또 다른 이유입니다python 3.x
eigenfield

36
>>> 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]

9

그러나 O (1) head,tail작업의 복잡성을 위해 사용해야합니다 deque.

다음 방법 :

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

목록의 모든 요소를 ​​반복해야 할 때 유용합니다. 예를 들어 병합 정렬에서 2 개의 파티션을 순진하게 병합합니다.


deque (list_instance)에 O (N) 복잡성이있는 것 같습니다. 내가 잘못?
Никита Конин

1
@ НикитаКонин, 당신은 deque의 건설에 대해 맞습니다. 그러나 첫 번째 요소에 두 번 이상 액세스하려면 head, tail = l.popleft(), l~ O (1)입니다. head, tail = seq[0], seq[1:]O (n)입니다.
Nikolay Fominyh

그것은 당신이 단지 할 수있는 모양 head = l.popleft()tail단지의 별칭입니다 l. 만약 l변경 tail도 변경됩니다.
kon psych

2

람다를 사용하는 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]

1
왜 세상에서 그냥 대신 이것을 head, tail = lst[0], lst[1:]하시겠습니까? 영업 수단은 문자를 사용하는 경우, 그는 수동으로 머리와 꼬리 나눌 수head, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
필리페 피나

1
(1) Op의 질문은 한 줄로 할 수 있는지 여부였습니다 ( 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].
BobIsNotMyName

즉, 나는 이것이 머리 / 꼬리를 얻는 나쁜 난독 화 된 방법임을 인정합니다. 하지만 Op의 특정 질문에 대한 Python 2에 대한 최고의 답변이라고 생각했습니다.
BobIsNotMyName

1

@GarethLattyPython 2 솔루션을 기반으로 빌드 한 다음은 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]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.