파이썬에서 "역전 된"목록을 만드는 가장 좋은 방법은 무엇입니까?


91

Python에서 항목이 다른 목록의 항목과 동일하지만 순서가 반대 인 새 목록을 만드는 가장 좋은 방법은 무엇입니까? (기존 목록을 수정하고 싶지 않습니다.)

다음은 나에게 발생한 한 가지 해결책입니다.

new_list = list(reversed(old_list))

복제 old_list한 다음 제자리에서 복제 를 되돌릴 수도 있습니다 .

new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()

내가 간과 한 더 나은 옵션이 있습니까? 그렇지 않다면 위의 접근 방식 중 하나를 다른 것보다 사용해야하는 설득력있는 이유 (예 : 효율성)가 있습니까?

답변:


207
newlist = oldlist[::-1]

[::-1]반대로 -1 단계, 즉,와, 슬라이스 전체 순서 : 내 아내 애나는 "화성 스마일";-) 수단 전화를 좋아하는 슬라이스 (. 모든 시퀀스에서 작동합니다.

이 항목 ( 언급 한 대안)은 "얕은 사본"과 동일합니다. 즉, 항목이 변경 가능하고 항목에 대해 mutator를 호출하면 원래 목록에있는 항목의 변경이 반전 된 목록 및 그 반대의 경우도 마찬가지입니다. 이를 피해야한다면 a copy.deepcopy(항상 비용이 많이 드는 작업) 다음에이 경우 a .reverse가 유일한 좋은 옵션입니다.


어머! 즉 이다 우아한. 며칠 전까지 만해도 슬라이싱 할 때 "단계"를 포함 할 수 있다는 것을 몰랐습니다. 이제 나는 그것없이 어떻게 지 냈는지 궁금합니다! 고마워, 알렉스. :)
davidchambers

1
또한 이것이 얕은 사본을 생성한다고 언급 해 주셔서 감사합니다. 그래도 그게 전부입니다. 이제 코드에 화성의 스마일리를 추가하려고합니다.
davidchambers

13
이것은 원래 제안보다 훨씬 더 마술적이고 읽기 어렵게 보입니다 list(reversed(oldlist)). 사소한 마이크로 최적화 외에 선호하는 이유 [::-1]reversed()있습니까?
Brian Campbell

@BrianCampbell : 그것에 대해 "마법"이란 무엇입니까? 슬라이싱을 전혀 이해하고 있다면 완전히 말이됩니다. 슬라이싱을 이해하지 못한다면 ... 글쎄, 파이썬 경력 초기에 배워야합니다. 물론 목록이 필요 하지 않은 경우에는 메모리를 낭비하거나 사전에 작성하는 시간이 필요하지 않기 때문에 reversed큰 이점이 있습니다 . 하지만이 때 사용하여 목록이 필요 대신 사용하여 유사 대신 . [::-1]list(reversed())[listcomp]list(genexpr)
abarnert

11
@abarnert 함께 작업하는 코드에서 세 번째 슬라이스 인수를 거의 볼 수 없습니다. 사용하는 경우 의미를 찾아야합니다. 일단 단계가 음수 일 때 기본 시작 및 종료 값이 바뀐다는 것이 여전히 명확하지 않습니다. 얼핏 보면 세 번째 인수의 의미를 찾지 않고 [::-1]목록의 마지막 요소를 뒤집는 것이 아니라 제거하는 것을 의미 한다고 생각할 수 있습니다 . reversed(list)그것이 무엇을하고 있는지 정확하게 설명합니다. "명시 적이 암시 적보다 낫다", "가독성이 중요하다", "희소가 조밀함보다 낫다"라는 의미로 의도를 설명합니다.
Brian Campbell

56

이제 timeit. 힌트 : Alex 's [::-1]가 가장 빠릅니다. :)

$ p -m timeit "ol = [1, 2, 3]; nl = list(reversed(ol))"
100000 loops, best of 3: 2.34 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = list(ol); nl.reverse();"
1000000 loops, best of 3: 0.686 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = ol[::-1];"
1000000 loops, best of 3: 0.569 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = [i for i in reversed(ol)];"
1000000 loops, best of 3: 1.48 usec per loop


$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 44.7 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(ol); nl.reverse();"
10000 loops, best of 3: 27.2 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = ol[::-1];"
10000 loops, best of 3: 24.3 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = [i for i in reversed(ol)];"
10000 loops, best of 3: 155 usec per loop

업데이트 : inspectorG4dget에서 제안한 list comp 메서드를 추가했습니다. 결과가 스스로 말하게 할 것입니다.


8
참고 사항-이것은 반전 된 사본 목록을 만드는 데 정확하지만 반전 된 것이 반복에 더 효율적입니다.[::-1]
Tadhg McDonald-Jensen

7

조정

종종 불필요한 list()변환 없이 'reversed'성능을 보여주는 sdolan의 timeit 계산에 대한 기준 벤치 마크 / 조정을 제공 할 가치가 있습니다. 이 list()작업은 런타임에 추가 26 개의 usec를 추가하며 반복기가 허용되지 않는 경우에만 필요합니다.

결과 :

reversed(lst) -- 11.2 usecs

list(reversed(lst)) -- 37.1 usecs

lst[::-1] -- 23.6 usecs

계산 :

# I ran this set of 100000 and came up with 11.2, twice:
python -m timeit "ol = [1, 2, 3]*1000; nl = reversed(ol)"
100000 loops, best of 3: 11.2 usec per loop

# This shows the overhead of list()
python -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 37.1 usec per loop

# This is the result for reverse via -1 step slices
python -m timeit "ol = [1, 2, 3]*1000;nl = ol[::-1]"
10000 loops, best of 3: 23.6 usec per loop

결론 :

이 테스트의 결론은 reversed()슬라이스보다 [::-1]12.4 usecs 더 빠릅니다.


15
reversed ()는 지연 평가 된 반복자 객체를 반환하므로 일반적으로 슬라이싱 표기법 [::-1]과 공정한 비교가 아니라고 생각합니다.
무지개 빛깔의

1
과 같이 반복기를 직접 사용할 수있는 경우에도 ''.join(reversed(['1','2','3']))slice 메서드는 여전히> 30 % 더 빠릅니다.
dansalmo 2013

1
처음 두 테스트에서 동일한 결과를 얻은 이유는 당연합니다. 모두 동일합니다!
MestreLion 2014-08-25

내 결과는 이것과 더 비슷합니다. ol [::-1]은 list (reversed (ol))의 두 배 정도 걸립니다. ol [::-1] 메서드는 쓰는 데 더 적은 문자가 필요합니다. 그러나 list (reversed (ol))는 아마도 초보자 파이썬 프로그래머에게 더 읽기 쉽고 내 컴퓨터에서 더 빠릅니다.
dhj
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.