색인을 알고있는 목록의 여러 요소에 액세스


232

주어진 목록에서 색인을 알고 일부 요소를 선택해야합니다. 주어진 목록 [-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]와 같은 것?


1
그건 그렇고, 나는 또 다른 해결책을 찾았습니다. 아직 테스트하지는 않았지만 code.activestate.com/recipes/…에
hoang tran

그것은 질문에서 언급 한 것과 동일한 해결책이지만 lambda함수에 싸여 있습니다.
Will Dereham

답변:


218

당신은 사용할 수 있습니다 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]

그러나 실제로는 현재 솔루션이 좋습니다. 아마도 그들 중 가장 끔찍할 것입니다.


35
c = [a[i] for i in b]완벽하게 언급하면 +1입니다 . 있습니다 itemgetterB 미만이 개 요소가있는 경우 해결책은 같은 일을하지 않습니다.
flornquake '

사이드 참고 : 사용 itemgetter를 다중 프로세스에서 작업하는 일을하지 않는 동안. Numpy는 다중 프로세스에서 훌륭하게 작동합니다.
Lior Magen

3
추가 의견, a[b]작동 할 때 aA는 NumPy와 배열, 당신은 NumPy와 기능을 만들 즉.
Ludwig Zhou

나는 비 NumPy와 옵션을 벤치마킹하고 itemgetter은 조금이라도 빨리, 가장 빠른 것으로 보인다 단순히 파이썬 3.44 사용하여 괄호 안에 원하는 인덱스를 입력하는 것보다
ragardner을

@ citizen2077, 설명하는 구문의 예를 들어 줄 수 있습니까?
alancalvitti

47

대안 :

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

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

첫 번째는 build-in함수 를 사용하기 때문에 좋습니다
silgon

첫 번째 문제는 __getitem__비교할 수없는 것처럼 보입니다. 예를 들어 항목 유형을 매핑하는 방법은 무엇입니까? map(type(a.__getitem__), b)
alancalvitti

@alancalvitti, lambda x: type(a.__getitem__(x)), b. 이 경우 사용 [..]이 더 간결합니다.lambda x: type(a[x]), b
falsetru

9

또 다른 해결책은 pandas Series를 통한 것일 수 있습니다.

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)

7

제공된 다섯 가지 답변의 실행 시간을 비교하는 기본적이고 광범위하지 않은 테스트 :

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]

다음 입력을 사용하여 :

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

간단한 파이썬 루프는 람다 연산이 가장 빠르며 두 번째로 빠르며 mapIndexValues ​​및 getIndexValues는 목록을 numpy 배열로 변환 한 후 numpy 메소드와 상당히 유사합니다. 가장 빠릅니다.

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

당신이 사용하는 인터프리터 내가 뭘 파이썬 모르지만 첫 번째 방법은 numpyIndexValues이후 일을하지 않는 a, b유형입니다 range. 난 당신이 변환에, 표준 추측하고 a, bnumpy.ndarrays먼저?
strpeter

@strpeter 예 사과를 사과와 비교하지 않았기 때문에 테스트 사례에서 numpyIndexValues에 대한 입력으로 numpy 배열을 만들었습니다. 나는 이것을 고쳤으며 모두 입력과 ​​동일한 목록을 사용합니다.
Don Smythe

4

나는 이것이 이미 고려되었다고 확신합니다 : b의 인덱스의 양이 작고 일정하다면 다음과 같은 결과를 쓸 수 있습니다.

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

또는 지수 자체가 상 수면 더 간단합니다 ...

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

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

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

상기시켜 주셔서 감사합니다[a] + [b] = [a, b]
onewhaleid

3

더 간단한 방법은 다음과 같습니다.

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

1

내 대답은 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를 사용하는 것이 좋습니다.


5
반복 할 필요가 없습니다 a. [a[i] for i in b]
falsetru

1
이 방법은 다른 경우에도 작동하지 않습니다. a다른 5 개가 있다면 ?
TerryA


b에 a의 크기를 초과하는 숫자가있는 경우 IndexErrors가 걱정되면[a[i] if i<len(a) else None for i in b]
576i

0

정적 인덱스와 작은 목록?

예제와 같이 목록이 작고 색인이 변경되지 않는 경우 시퀀스 풀림 을 사용하는 것이 가장 좋습니다 .

_,a1,a2,_,_,a3,_ = a

성능이 훨씬 우수하며 한 줄의 코드를 저장할 수도 있습니다.

 %timeit _,a1,b1,_,_,c1,_ = a
10000000 loops, best of 3: 154 ns per loop 
%timeit itemgetter(*b)(a)
1000000 loops, best of 3: 753 ns per loop
 %timeit [ a[i] for i in b]
1000000 loops, best of 3: 777 ns per loop
 %timeit map(a.__getitem__, b)
1000000 loops, best of 3: 1.42 µs per loop

0

파이 토닉 방식 :

c = [x for x in a if a.index(x) in b]

2
나는 이것이 OP의 예보다 덜 "피 토닉"이라고 말하고 싶습니다 . 코드 길이를 거의 두 배로 늘리면서 O(n)솔루션으로 솔루션 을 전환했습니다 O(n^2). 또한 목록이 경우 물체가 흐리거나 부분적인 평등, 예를 들어 것입니다 포함 된 경우 실패합니다 그 방법을주의하는 것이 좋습니다 a포함 float('nan'),이 것 항상 인상 ValueError.
브라이언
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.