인덱스를 알고 목록의 여러 요소에 액세스
지정된 목록에서 인덱스를 알고 몇 가지 요소를 선택해야 합니다.지정된 목록 [-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]와 같은 더 좋은 방법은 없을까?
다음을 사용할 수 있습니다.
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]
하지만 현재의 솔루션은 문제 없습니다.아마 그중에서 제일 깔끔할 거예요.
다른 방법:
>>> map(a.__getitem__, b)
[1, 5, 5]
>>> import operator
>>> operator.itemgetter(*b)(a)
(1, 5, 5)
또 다른 솔루션은 Panda 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)
제공된 5가지 답변의 실행 시간을 비교하는 기본적이고 그다지 광범위하지 않은 테스트:
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)
단순 python 루프는 lambda 연산에서 가장 빨랐고 mapIndexValues와 getIndexValues는 목록을 numpy 배열로 변환한 후 numpy 메서드에서 상당히 느렸습니다.데이터가 이미 numpy 배열에 있는 경우 numpy는numpy.array 변환을 제거한 IndexValues 메서드가 가장 빠릅니다.
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
보다 심플한 방법은 다음과 같습니다.
a = [-2,1,5,3,8,5,6]
b = [1,2,5]
c = [e for i, e in enumerate(a) if i in b]
이것은 이미 고려되었을 것입니다.b의 지수 양이 작고 일정하다면 다음과 같이 결과를 쓸 수 있다.
c = [a[b[0]]] + [a[b[1]]] + [a[b[2]]]
또는 지수 자체가 상수인 경우에는...
c = [a[1]] + [a[2]] + [a[5]]
또는 연속된 지수 범위가 있는 경우...
c = a[1:3] + [a[5]]
목록 이해는 분명히 가장 즉각적이고 기억하기 쉬운 것이다 - 게다가 꽤 버마적인 것이다!
어쨌든 제안된 솔루션 중 가장 빠르지 않습니다(Python 3.8.3을 사용하여 Windows에서 테스트를 실행했습니다).
import timeit
from itertools import compress
import random
from operator import itemgetter
import pandas as pd
__N_TESTS__ = 10_000
vector = [str(x) for x in range(100)]
filter_indeces = sorted(random.sample(range(100), 10))
filter_boolean = random.choices([True, False], k=100)
# Different ways for selecting elements given indeces
# list comprehension
def f1(v, f):
return [v[i] for i in filter_indeces]
# itemgetter
def f2(v, f):
return itemgetter(*f)(v)
# using pandas.Series
# this is immensely slow
def f3(v, f):
return list(pd.Series(v)[f])
# using map and __getitem__
def f4(v, f):
return list(map(v.__getitem__, f))
# using enumerate!
def f5(v, f):
return [x for i, x in enumerate(v) if i in f]
# using numpy array
def f6(v, f):
return list(np.array(v)[f])
print("{:30s}:{:f} secs".format("List comprehension", timeit.timeit(lambda:f1(vector, filter_indeces), number=__N_TESTS__)))
print("{:30s}:{:f} secs".format("Operator.itemgetter", timeit.timeit(lambda:f2(vector, filter_indeces), number=__N_TESTS__)))
print("{:30s}:{:f} secs".format("Using Pandas series", timeit.timeit(lambda:f3(vector, filter_indeces), number=__N_TESTS__)))
print("{:30s}:{:f} secs".format("Using map and __getitem__", timeit.timeit(lambda: f4(vector, filter_indeces), number=__N_TESTS__)))
print("{:30s}:{:f} secs".format("Enumeration (Why anyway?)", timeit.timeit(lambda: f5(vector, filter_indeces), number=__N_TESTS__)))
결과는 다음과 같습니다.
목록 이해: 0.007113초
Operator.itemgetter : 0.003247초
팬더 시리즈 사용 : 2.977286초
맵과 get item 사용 : 0.005029초
열거(어차피 왜?): 0.135156초
수치: 0.157018초
제 답변은 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를 사용하는 것이 좋습니다.
정적 인덱스 및 소규모 목록?
리스트가 작고 인덱스가 변경되지 않는 경우, 경우에 따라 가장 좋은 방법은 시퀀스 언팩을 사용하는 것입니다.
_,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
일종의 비토닉 방식:
c = [x for x in a if a.index(x) in b]
<<고객명>>의 결과pandas==1.4.22022년 6월 6일
단순한 슬라이스는 더 이상 불가능하며 벤치마크 결과가 더 빨라집니다.
import timeit
import pandas as pd
print(pd.__version__)
# 1.4.2
pd.Series([-2, 1, 5, 3, 8, 5, 6])[1, 2, 5]
# KeyError: 'key of type tuple not found and not a MultiIndex'
pd.Series([-2, 1, 5, 3, 8, 5, 6]).iloc[[1, 2, 5]].tolist()
# [1, 5, 5]
def extract_multiple_elements():
return pd.Series([-2, 1, 5, 3, 8, 5, 6]).iloc[[1, 2, 5]].tolist()
__N_TESTS__ = 10_000
t1 = timeit.timeit(extract_multiple_elements, number=__N_TESTS__)
print(round(t1, 3), 'seconds')
# 1.035 seconds
언급URL : https://stackoverflow.com/questions/18272160/access-multiple-elements-of-list-knowing-their-index
'source' 카테고리의 다른 글
| 형식 매개 변수의 개체를 인스턴스화하는 중 (0) | 2022.09.08 |
|---|---|
| Intelij IDEA에서 텍스트를 새 줄로 바꾸려면 어떻게 해야 합니까? (0) | 2022.09.08 |
| 단수 또는 복수 데이터베이스 테이블 이름? (0) | 2022.09.08 |
| 테이블의 기본 키를 리셋하려면 어떻게 해야 합니까? (0) | 2022.09.08 |
| tail과 유사한 파일의 마지막 n 행을 가져옵니다. (0) | 2022.09.08 |