Python : n 개의 목록을 만드는 가장 빠른 방법


97

그래서 빈 목록 목록을 가장 잘 만드는 방법이 궁금합니다.

[[],[],[]...]

파이썬이 메모리의 목록과 함께 작동하는 방식 때문에 작동하지 않습니다.

[[]]*n

이것은 생성 [[],[],...]되지만 각 요소는 동일한 목록입니다.

d = [[]]*n
d[0].append(1)
#[[1],[1],...]

목록 이해와 같은 것이 작동합니다.

d = [[] for x in xrange(0,n)]

그러나 이것은 루핑을 위해 Python VM을 사용합니다. 묵시적 루프를 사용하는 방법이 있습니까 (C로 작성된 이점을 활용)?

d = []
map(lambda n: d.append([]),xrange(0,10))

이것은 실제로 더 느립니다. :(


1
보다 상당히 빠른 것이 있다면 놀랄 것 d = [[] for x in xrange(0,n)]입니다. Python에서 명시 적으로 반복하거나 Python 함수 / 람다를 반복적으로 호출해야합니다 (더 느려 야 함). 그러나 여전히 누군가가 내가 틀렸다는 것을 보여주는 것을 게시하기를 바랍니다. :).
MAK

1
로 이것을 측정했을 때 timeit무엇을 배웠습니까?
S.Lott 2011

나는 그것이 map(lambda x: [], xrange(n))목록 이해보다 느리다는 것을 방금 확인했습니다 .
Andrew Clark

답변:


105

아마 조금 더 빠른 유일한 방법은

d = [[] for x in xrange(n)]

이다

from itertools import repeat
d = [[] for i in repeat(None, n)]

int모든 반복에서 새 객체 를 만들 필요가 없으며 내 컴퓨터에서 약 15 % 더 빠릅니다.

편집 : NumPy를 사용하면 다음을 사용하여 Python 루프를 피할 수 있습니다.

d = numpy.empty((n, 0)).tolist()

그러나 이것은 실제로 목록 이해보다 2.5 배 느립니다.


어때요 map(lambda x:[], repeat(None,n))?
PaulMcG 2011

3
@Paul : 람다 식의 함수 호출 오버 헤드로 인해 다시 느려질 것입니다.
Sven Marnach

Python 3에서 범위가 다르기 때문에 지금 업데이트해야하지 않습니까?
beruic

@beruic 첫 번째 코드 블록에서 질문의 코드를 인용하고 있으므로 변경하는 것이 실제로 의미가 없습니다.
스벤 Marnach

12

목록 내포는 실제로 명시 적 루프 ( 예 : 함수 dis출력 참조)보다 더 효율적으로 구현 되며, map방법은 매 반복마다 ophaque 호출 가능 객체를 호출해야하므로 상당한 오버 헤드가 발생합니다.

그럼에도 불구하고 [[] for _dummy in xrange(n)]그것을 수행하는 올바른 방법이며 다양한 다른 방법 간의 작은 속도 차이 중요하지 않습니다. 물론이 작업에 대부분의 시간을 소비하지 않는 한-이 경우 대신 알고리즘 작업을해야합니다. 이 목록을 얼마나 자주 만드십니까?


5
_변수 이름으로 아니요 ! 그렇지 않으면 좋은 대답 :)
Sven Marnach 2011-04-01

11
@Sven : 왜 안돼? 일반적으로 사용되지 않는 변수에 사용됩니다 (라고 부르면 i사용 된 위치를 찾고 있습니다). 유일한 함정은 _REPL의 마지막 결과를 숨기는 것입니다. 그리고 그것은 목록 이해가 누출되는 2.x의 경우에만 해당됩니다.

그다지 자주는 아니기 때문에 목록 이해력을 사용했습니다. 사람들이 무슨 말을해야하는지 보는 것이 재미있을 것이라고 생각했습니다. md5 해시를 엄청나게 많이 업데이트하기 위해 for 루프 대신 itertools.imap을 사용하여 PyCon에서 Dropbox 이야기를 보았고 그 이후로 C 루프에 약간 집착했습니다.
munchybunch 2011

12
그것을 사용하지 않는 가장 중요한 이유는 사람들을 혼란스럽게 만드는 경향이있어서 일종의 특별한 구문이라고 생각하게하기 때문입니다. 그리고 _대화 형 인터프리터에서 의 충돌 외에도 일반적인 gettext 별칭과 충돌합니다. 당신이 변수가 더미 변수임을 분명히 확인하려면 호출 dummy하지 _.
Sven Marnach

12

다음은 달콤하고 단순한 (및 개념적) 두 가지 방법이고 다른 하나는보다 형식적이며 데이터 세트를 읽은 후 다양한 상황에서 확장 할 수 있습니다.

방법 1 : 개념

X2=[]
X1=[1,2,3]
X2.append(X1)
X3=[4,5,6]
X2.append(X3)
X2 thus has [[1,2,3],[4,5,6]] ie a list of lists. 

방법 2 : 공식 및 확장 가능

다른 번호 목록으로 목록을 저장하는 또 다른 우아한 방법-파일에서 읽습니다. (여기 파일에는 데이터 셋 train이 있습니다.) Train은 50 개의 행과 20 개의 열로 구성된 데이터 세트입니다. 즉. Train [0]은 csv 파일의 첫 번째 행을 제공하고 train [1]은 두 번째 행을 제공하는 식입니다. 여기에 설명 된 변수 인 0 열을 제외하고는 50 개의 행이있는 데이터 세트를 하나의 목록으로 분리하는 데 관심이 있으므로 원래 기차 데이터 세트에서 제거해야합니다. . 이를 수행하는 코드는 다음과 같습니다.

설명 변수에만 관심이 있으므로 내부 루프의 "1"에서 읽습니다. 그리고 다른 루프에서 X1 = []을 다시 초기화합니다. 그렇지 않으면 X2.append ([0 : (len (train [0])-1)])가 X1을 반복해서 다시 작성합니다.

X2=[]
for j in range(0,len(train)):
    X1=[]
    for k in range(1,len(train[0])):
        txt2=train[j][k]
        X1.append(txt2)
    X2.append(X1[0:(len(train[0])-1)])

4

목록 및 목록 목록을 만들려면 아래 구문을 사용하십시오.

     x = [[] for i in range(10)]

이것은 1-d 목록을 생성하고 초기화하기 위해 [[number]에 숫자를 넣고 목록의 길이를 범위 (length)에 넣습니다.

  • 목록 목록을 만들려면 아래 구문을 사용하십시오.
    x = [[[0] for i in range(3)] for i in range(10)]

이것은 10 * 3 차원과 0 값으로 목록 목록을 초기화합니다.

  • 요소에 액세스 / 조작하려면
    x[1][5]=value

2

그래서 저는 가장 빠른 방법을 얻기 위해 몇 가지 속도 비교를했습니다. 목록 이해는 실제로 매우 빠릅니다. 가까워지는 유일한 방법은 목록을 구성하는 동안 바이트 코드가 제외되지 않도록하는 것입니다. 내 첫 번째 시도는 다음과 같은 방법으로 원칙적으로 더 빠른 것으로 보입니다.

l = [[]]
for _ in range(n): l.extend(map(list,l))

(물론 길이 2 ** n의 목록을 생성합니다) timeit에 따르면이 구조는 짧은 목록과 긴 목록 (백만 개) 모두에 대해 목록 이해력보다 두 배 느립니다.

두 번째 시도는 스타 맵을 사용하여 목록 생성자를 호출하는 것이 었습니다. 목록 생성자를 최고 속도로 실행하는 것처럼 보이지만 여전히 느리지 만 아주 적은 양의 구성이 있습니다.

from itertools import starmap
l = list(starmap(list,[()]*(1<<n)))

실행 시간이 흥미 롭다는 것은 실행 시간이 다음의 속도와 거의 정확히 같기 때문에 스타 맵 솔루션을 느리게 만드는 최종 목록 호출임을 시사합니다.

l = list([] for _ in range(1<<n))

내 세 번째 시도는 list (())도 목록을 생성한다는 것을 깨달았을 때 왔기 때문에 매우 간단한 시도를했습니다.

l = list(map(list, [()]*(1<<n)))

하지만 이것은 스타 맵 호출보다 느 렸습니다.

결론 : 스피드 매니아를 위해 : 목록 이해력을 사용하십시오. 필요한 경우에만 함수를 호출하십시오. 내장 기능을 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.