それらのインデックスを知って、与えられたリストからいくつかの要素を選択する必要があります。与えられたリスト[-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]のようなものですか?
lambda
関数にラップされています。
それらのインデックスを知って、与えられたリストからいくつかの要素を選択する必要があります。与えられたリスト[-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]のようなものですか?
lambda
関数にラップされています。
回答:
使用できます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]
しかし、実際には、現在のソリューションは問題ありません。それはおそらくそれらすべての中で最も控えめなものです。
c = [a[i] for i in b]
ます。itemgetter
bの要素が2つ未満の場合、解は同じことを行わないことに注意してください。
a[b]
作品のみときa
ですnumpyの配列は、あなたがnumpyの機能とそれを作成しますすなわち。
代替案:
>>> map(a.__getitem__, b)
[1, 5, 5]
>>> import operator
>>> operator.itemgetter(*b)(a)
(1, 5, 5)
build-in
関数は関数を使用するので便利です
__getitem__
たとえばアイテムのタイプをマップする方法など、互換性がないように見えることですか?map(type(a.__getitem__), b)
lambda x: type(a.__getitem__(x)), b
. この場合、使用しては、[..]
よりコンパクトである:lambda x: type(a[x]), b
提供された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ループはラムダ操作が1秒近くで最も速く、リストをnumpy配列に変換した後、mapIndexValuesとgetIndexValuesはnumpyメソッドと一貫してかなり遅くなりました。データが既にnumpy配列にある場合、numpy.array変換を削除したnumpyIndexValuesメソッドは最速。
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
b
numpy.ndarrays
私はこれがすでに考慮されていると確信しています: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]
私の答えは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の使用をお勧めします。
a
。[a[i] for i in b]
a
さらに5つあった場合はどうなりますか?
[a[i] if i<len(a) else None for i in b]
例のように、リストが小さく、インデックスが変更されない場合は、シーケンスのアンパッキングを使用するのが最善の場合があることを忘れないでください。
_,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
Python的な方法の種類:
c = [x for x in a if a.index(x) in b]
O(n)
、O(n^2)
ソリューションをソリューションに変えることができました。リストにオブジェクトが含まれている場合、アプローチが失敗することにも注意してください。たとえば、a
が含まれている場合float('nan')
、これにより常にが発生しValueError
ます。