web-dev-qa-db-ja.com

インデックスを知っているリストの複数の要素にアクセスする

与えられたリストからいくつかの要素を選び、それらのインデックスを知る必要があります。与えられたリスト[-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]のようなもの?

179
hoang tran

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]

しかし、実際には、現在の解決策は問題ありません。それはおそらくそれらすべての中で最も新しいです。

172
TerryA

代替案:

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

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

別の解決策はパンダシリーズを介してすることができます:

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
BossaNova

提供された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ループはラムダ演算のすぐ近くにあり、mapIndexValuesとgetIndexValuesは一貫して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
3
Don Smythe

私はこれがすでに考慮されていると確信しています:bの中のインデックスの量が小さくて一定であるならば、ただ次のような結果を書くことができます:

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

あるいは、インデックス自体が定数の場合はもっと単純です。

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

または連続した範囲のインデックスがある場合...

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

私の答えは、でこぼこやPythonのコレクションを使用していません。

要素を見つけるための簡単な方法は次のとおりです。

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

欠点:この方法は大きなリストでは動作しないかもしれません。大きなリストの場合は、numpyを使用することをお勧めします

0
Lavya 'Orion'

静的インデックスと小さなリスト?

あなたの例のように、リストが小さく、インデックスが変更されない場合、 sequence unpacking を使用することが最善の場合があることを忘れないでください。

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

パフォーマンスは大幅に向上し、1行のコードを保存することもできます。

 %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
G M