2013-08-16 1 views
112

주어진 목록에서 색인을 아는 일부 요소를 선택해야합니다. 주어진리스트 [-2, 1, 5, 3, 8, 5, 6]에서 인덱스 1, 2, 5가있는 요소를 포함하는 새 목록을 만들고 싶습니다. 내가 한 것은 :색인을 알고있는 목록의 여러 요소에 액세스하십시오.

a = [-2,1,5,3,8,5,6] 
b = [1,2,5] 
c = [ a[i] for i in b] 

그것을 할 수있는 더 좋은 방법이 있나요? c = a [b]와 같은 무엇인가?

+0

, 여기 또 다른 해결책을 발견 . 아직 테스트하지는 않았지만 http://code.activestate.com/recipes/577953-get-multiple-elements-from-a-list/ –

+0

에 관심이 있으면 여기에 게시 할 수 있다고 생각합니다. 질문에서 언급 한 것과 같은 해결책이지만'lambda' 함수로 싸여 있습니다. –

+0

[목록에서 요소를 추출하는 방법은?] (https://stackoverflow.com/questions/2621674/how-to-extract-elements-from-a-list-in-python) – jdhao

답변

113

당신은 operator.itemgetter 사용할 수 있습니다

from operator import itemgetter 
a = [-2, 1, 5, 3, 8, 5, 6] 
b = [1, 2, 5] 
print itemgetter(*b)(a) 
# Result: 
(1, 5, 5) 

또는 당신은 사용할 수 있습니다 numpy :

import numpy as np 
a = np.array([-2, 1, 5, 3, 8, 5, 6]) 
b = [1, 2, 5] 
print list(a[b]) 
# Result: 
[1, 5, 5] 

하지만 실제로는 현재 해결책이 좋습니다. 그것은 아마도 그들 모두에서 가장 깨끗합니다.

+14

+1 'c = [a [i] for i in b]는 완벽하게 괜찮습니다. 'itemgetter' 솔루션은 b가 2 개 미만의 원소를 가진다면 똑같은 일을하지 않을 것입니다. – flornquake

+0

** 측면 ** ** 참고 ** : 다중 프로세스에서 작업하는 동안 _itemgetter_ 사용은 작동하지 않습니다. Numpy는 다중 프로세스에서 뛰어납니다. –

+0

'a'가 ** numpy ** 배열 일 때 추가 주석 인'a [b]'** ** 만 작동합니다. 즉, numpy 함수로 생성합니다. –

22

대안 :

>>> map(a.__getitem__, b) 
[1, 5, 5] 

>>> import operator 
>>> operator.itemgetter(*b)(a) 
(1, 5, 5) 
0

내 대답은 numpy 또는 python 모음을 사용하지 않습니다. 다음과 같은 요소가 될 것이다 찾을 수

한 사소한 방법 :

a = [-2, 1, 5, 3, 8, 5, 6] 
b = [1, 2, 5] 
c = [i for i in a if i in b] 

단점 :이 방법은 큰 목록에 대한 작동하지 않을 수 있습니다. 큰 목록에는 numpy를 사용하는 것이 좋습니다. 다음 입력을 사용

def numpyIndexValues(a, b): 
    na = np.array(a) 
    nb = np.array(b) 
    out = list(na[nb]) 
    return out 

def mapIndexValues(a, b): 
    out = map(a.__getitem__, b) 
    return list(out) 

def getIndexValues(a, b): 
    out = operator.itemgetter(*b)(a) 
    return out 

def pythonLoopOverlap(a, b): 
    c = [ a[i] for i in b] 
    return c 

multipleListItemValues = lambda searchList, ind: [searchList[i] for i in ind] 

: 다섯 개 공급 응답의 실행 시간을 비교

+3

'a'를 반복 할 필요가 없습니다. '[i [i] for b] ' – falsetru

+0

이 방법은 다른 경우에는 작동하지 않습니다. 'a'가 5를 더 넣으면 어떨까요? – TerryA

+0

IMO, [sets] (https://docs.python.org/3/tutorial/datastructures.html#sets) – sirgogo

3

기본 아니라 매우 광범위한 테스트

a = range(0, 10000000) 
b = range(500, 500000) 

간단한 파이썬 루프이었다 람다 동작 A의 빠른 두 번째 닫기, mapIndexValues ​​및 getIndexValues는 numpy 메소드와 일관되게 매우 유사했습니다. 목록이 numpy 배열로 변환 된 후 상당히 느립니다. 데이터가 이미 numpy 배열에있는 경우 numpy가있는 numpyIndexValues ​​메소드 .array 변환이 가장 빠릅니다.

numpyIndexValues -> time:1.38940598 (when converted the lists to numpy arrays) 
numpyIndexValues -> time:0.0193445 (using numpy array instead of python list as input, and conversion code removed) 
mapIndexValues -> time:0.06477512099999999 
getIndexValues -> time:0.06391049500000001 
multipleListItemValues -> time:0.043773591 
pythonLoopOverlap -> time:0.043021754999999995 
+0

을 사용하여이 종류의 교차를 더 빨리 수행 할 수 있습니다. 파이썬 인터프리터를 사용하는 방법을 모르지만 첫 번째 방법 인' numpyIndexValues'는'a','b'는'range' 타입이므로 작동하지 않습니다. 나는 당신이'a''''''''를'numpy.ndarrays'''로 먼저 변환시키는 것을 추측하고 있습니까? – strpeter

+0

@strpeter 예 사과와 사과를 비교하지 않고 있었기 때문에 numpyIndexValues에 대한 테스트 케이스에 입력으로 누더기 배열을 만들었습니다. 나는 이것을 지금 고쳤으며 모두 같은 목록을 입력으로 사용한다. –

2

나는이 이미 고려 된 확신 :

c = [a[b[0]]] + [a[b[1]]] + [a[b[2]]] 

또는 인덱스 경우 더 간단 : B의 ​​인덱스의 양이 작고 일정한 경우, 하나는 같은 결과를 쓸 수 그 자체가 ...

c = [a[1]] + [a[2]] + [a[5]] 

상수 또는 인덱스의 연속 범위가있는 경우 ...

c = a[1:3] + [a[5]] 
+0

제게 '[a] + [b] = [a, b]' – onewhaleid

1

또 다른 해결책은 팬더 시리즈를 통해 수 :

import pandas as pd 

a = pd.Series([-2, 1, 5, 3, 8, 5, 6]) 
b = [1, 2, 5] 
c = a[b] 

그런 다음 다시 당신이 원하는 경우 목록에 C를 변환 할 수 있습니다 : 그런데

c = list(c) 
관련 문제