더 큰 목록에서 모든 n 번째 항목의 목록을 반환하는 Pythonic 방법


170

우리가 0에서 1000까지의 숫자 목록을 가지고 있다고 가정 해보십시오. 첫 번째 및 모든 후속 10 번째 항목의 목록을 생성하는 파이썬적이고 효율적인 방법이 [0, 10, 20, 30, ... ]있습니까?

예, for 루프를 사용 하여이 작업을 수행 할 수 있지만 한 줄로도 더 깔끔한 방법이 있는지 궁금합니다.

답변:


289
>>> lst = list(range(165))
>>> lst[0::10]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]

이는 각 요소의 계수를 루핑하고 확인하는 것보다 약 100 배 빠릅니다.

$ python -m timeit -s "lst = list(range(1000))" "lst1 = [x for x in lst if x % 10 == 0]"
1000 loops, best of 3: 525 usec per loop
$ python -m timeit -s "lst = list(range(1000))" "lst1 = lst[0::10]"
100000 loops, best of 3: 4.02 usec per loop

4
물론, 목록 이해력이 일반적으로 더 강력합니다. OTOH, 질문은 기존 목록을 표시하며,이 경우 슬라이스가 제대로 작동합니다.
Ned Deily

나는 아래의 목록 이해 답변에 이것을 언급했다. "if x % 10 == 0"인 경우주의하십시오. 이 특정 목록 예제에서만 작동하지만 입력 목록이 예를 들어 l = range (0,1000,2)이면 매 10 번째 항목을 꺼내지 않습니다.
Andre Miller

12
@Andre : 매우 그렇습니다. 따라서 이것은 겸손한 언어 기능인 슬라이스 연산자의 예입니다.이 경우에는 올바른 결과를보다 쉽게 ​​얻을 수 있도록이 경우 (1)로 나타납니다. (2)보다 간결한 표현을 제공합니다. (3) 2 배 더 빠릅니다. (1) 물론 가장 중요한 관심사이지만 언어의 신중한 디자인과 구현 덕분에 세 가지 모두 1의 가격으로 얻을 수 있습니다. 멋진 질문과 답변.
Ned Deily

2
0에서 중복됩니다 l[0::10]. l[::10]더 읽기 쉽고 혼동되지 않습니다.
Konstantin Schubert

목록 이해의 경우 0.5 초, 목록 조각의 경우 0.4 초의 성능 비교에 놀랐습니다. 목록 슬라이싱에 1 천 크기의 목록에 10 만 개의 루프가 필요한 이유는 매우 느린 것 같습니다!?
Damo

57
  1. source_list[::10] 가장 명백하지만 반복 가능한 경우 작동하지 않으며 큰 목록의 경우 메모리 효율적이지 않습니다.
  2. itertools.islice(source_sequence, 0, None, 10) iterable에 대해 작동하고 메모리 효율적이지만 큰 목록과 큰 단계를위한 가장 빠른 솔루션은 아닙니다.
  3. (source_list[i] for i in xrange(0, len(source_list), 10))

1
+1 최고의 답변, IMO. 세 가지 제안 모두 일반적인 솔루션입니다 (예 : 주어진 소스 목록을 가져옴). 생성기 솔루션 (3.)은 소스 목록의 인덱스를 필터링하므로 유용합니다. 아마도 2만큼 메모리 효율적일 것입니다. 인덱스와 결과 목록은 생성기이므로 느리게 구성됩니다. 결과 목록이 단일 청크로 필요하지 않은 경우 가장 빠릅니다. 소스리스트가 제너레이터 일 수있는 경우에만 제너레이터의 len ()이 없기 때문에 Paul의 "아이템, 나는 enumerate (l)"관용구와 함께 갈 것입니다. BTW, 어떤 종류의 iterable이 1에서 작동하지 않습니까? 발전기?!
ThomasH

반복 가능한 반복자 (다음 () 메소드 Object)를 반환하는 방법) (__ __iter와 개체 =
데니스 Otkidach


19

수동에서 : s[i:j:k] slice of s from i to j with step k

li = range(100)
sub = li[0::10]

>>> sub
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]


4

range 함수 의 step 매개 변수를 사용 하여 얻을 수 있습니까?

l = range(0, 1000, 10)

비교를 위해 내 컴퓨터에서

H:\>python -m timeit -s "l = range(1000)" "l1 = [x for x in l if x % 10 == 0]"
10000 loops, best of 3: 90.8 usec per loop
H:\>python -m timeit -s "l = range(1000)" "l1 = l[0::10]"
1000000 loops, best of 3: 0.861 usec per loop
H:\>python -m timeit -s "l = range(0, 1000, 10)"
100000000 loops, best of 3: 0.0172 usec per loop

3
@SilentGhost : 사실이지만, 이것은 초보 질문이므로 범위 함수가 실제로 하고 싶은 것이 될 수 있으므로 올바른 대답이라고 생각합니다. (상한은 없다 1000 1001이어야하지만)
스콧 그리피스

2
existing_list = range(0, 1001)
filtered_list = [i for i in existing_list if i % 10 == 0]

1
range (0, 1001, 10)이 10 번째 요소마다 이미 필요한 경우 왜 if 절이 있습니까?
Autoplectic September

4
여기에 동일한 의견이 있습니다.이 방법은 "큰 목록의 모든 n 번째 항목 목록을 반환하는 Pythonic 방법"의 더 일반적인 문제를 해결하지 못합니다. 솔루션은 예제 목록의 값이 0-1000이고 항목 만 가져 오는 사실에 달려 있습니다 목록에서 10 번째 항목 대신 10으로 나눌 수있는 값을 갖습니다.
Andre Miller

1
OP는 다음과 같이 말합니다. "0에서 1000까지의 숫자 목록이 있습니다." 따라서 그는 일반적인 솔루션이 필요하지 않습니다.

1
그는 '우리에게 말해 ..'라고 적혀 있습니다. 그가 실제로 0에서 1000까지의 목록에서 10 번째 숫자를 원한다면 range (0,1001,10) 또는 이와 비슷한 것입니다.
Andre Miller

1

다음은 멤버십 테스트의 일부로 목록 컨텐츠를 사용하지 않는 "모든 10 번째 항목"목록 이해의 더 나은 구현입니다.

>>> l = range(165)
>>> [ item for i,item in enumerate(l) if i%10==0 ]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
>>> l = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
>>> [ item for i,item in enumerate(l) if i%10==0 ]
['A', 'K', 'U']

그러나 이것은 목록 슬라이싱을 사용하는 것보다 훨씬 느립니다.


-9

이를 위해 목록 이해가 정확하게 이루어집니다.

smaller_list = [x for x in range(100001) if x % 10 == 0]

파이썬 공식 문서에서 더 많은 정보를 얻을 수 있습니다. http://docs.python.org/tutorial/datastructures.html#list-comprehensions


상한은 10000이 아닌 1000이어야합니다. 범위가 999에서 중지되므로 솔루션에 상한은 1000이 포함되지 않습니다. 목록 이해에 대한 링크의 경우 +1입니다.

19
이것은 실제로 모든 10 번째 항목을 꺼내지 않고 10으로 나눌 수있는 값을 가진 모든 항목을 가져옵니다.이 특정 예제에서는 동일하지만 그렇지 않을 수 있습니다.
Andre Miller
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.