web-dev-qa-db-ja.com

指定されたインデックスで、Pythonリストのサブリストを取得しますか?

Pythonリスト、たとえばa = [0,1,2,3,4,5,6]。インデックスのリストもあります。たとえば、b = [0,2,4,5]aのインデックスを持つbの要素のリストを取得するにはどうすればよいですか?

22
becko

list comprehensionを使用して、そのリストを取得できます。

c = [a[index] for index in b]
print c

これは次と同等です:

c= []
for index in b:
    c.append(a[index])
print c

出力:

[0,2,4,5]

注:

some_list[index]は、特定のインデックス内のlistの要素にアクセスするために使用される表記法です。

34
Christian

何か違います...

>>> a = range(7)
>>> b = [0,2,4,5]
>>> import operator
>>> operator.itemgetter(*b)(a)
(0, 2, 4, 5)

itemgetter 関数は、引数として1つ以上のキーを取り、its引数。そのため、上記では、インデックス0、インデックス2、インデックス4、インデックス5のアイテムを返す関数を作成し、その関数をaに適用します。

同等のリストの理解よりもかなり速いようです

In [1]: import operator

In [2]: a = range(7)

In [3]: b = [0,2,4,5]

In [4]: %timeit operator.itemgetter(*b)(a)
1000000 loops, best of 3: 388 ns per loop

In [5]: %timeit [ a[i] for i in b ]
1000000 loops, best of 3: 415 ns per loop

In [6]: f = operator.itemgetter(*b)

In [7]: %timeit f(a)
10000000 loops, best of 3: 183 ns per loop

itemgetterの方が速い理由については、内包表記では余分なPythonバイトコードを実行する必要があります。

In [3]: def f(a,b): return [a[i] for i in b]

In [4]: def g(a,b): return operator.itemgetter(*b)(a)

In [5]: dis.dis(f)
  1           0 BUILD_LIST               0
              3 LOAD_FAST                1 (b)
              6 GET_ITER
        >>    7 FOR_ITER                16 (to 26)
             10 STORE_FAST               2 (i)
             13 LOAD_FAST                0 (a)
             16 LOAD_FAST                2 (i)
             19 BINARY_SUBSCR
             20 LIST_APPEND              2
             23 JUMP_ABSOLUTE            7
        >>   26 RETURN_VALUE

itemgetterはCで実装された単一の呼び出しです:

In [6]: dis.dis(g)
  1           0 LOAD_GLOBAL              0 (operator)
              3 LOAD_ATTR                1 (itemgetter)
              6 LOAD_FAST                1 (b)
              9 CALL_FUNCTION_VAR        0
             12 LOAD_FAST                0 (a)
             15 CALL_FUNCTION            1
             18 RETURN_VALUE
22
chepner

関数型プログラミング が好きなら、 maplist.__getitem__

>>> a = [0,1,2,3,4,5,6]
>>> b = [0,2,4,5]
>>> map(a.__getitem__, b)
[0, 2, 4, 5]
>>>

リスト内包アプローチは、Python.

8
iCodez

Python辞書:キーのリストの値のリストを取得

_Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Jan 19 2016, 12:08:31) [MSC v.1500 64 bit (AMD64)] on win32

In[2]: import numpy.random as nprnd
idx = nprnd.randint(1000, size=10000)
l = nprnd.Rand(1000).tolist()
from operator import itemgetter
import operator
f = operator.itemgetter(*idx)
%timeit f(l)
%timeit list(itemgetter(*idx)(l))
%timeit [l[_] for _ in idx]  # list comprehension
%timeit map(l.__getitem__, idx)
%timeit list(l[_] for _ in idx)  # a generator expression passed to a list constructor.
%timeit map(lambda _: l[_], idx)  # using 'map'
%timeit [x for i, x in enumerate(l) if i in idx]
%timeit filter(lambda x: l.index(x) in idx, l)  # UPDATE @Kundor: work only for list with unique elements
10000 loops, best of 3: 175 µs per loop
1000 loops, best of 3: 707 µs per loop
1000 loops, best of 3: 978 µs per loop
1000 loops, best of 3: 1.03 ms per loop
1000 loops, best of 3: 1.18 ms per loop
1000 loops, best of 3: 1.86 ms per loop
100 loops, best of 3: 12.3 ms per loop
10 loops, best of 3: 21.2 ms per loop
_

最速はf = operator.itemgetter(*idx); f(l)です

3
Sklavit

提案されたソリューションの多くは、KeyErrorbに存在しないインデックスが含まれている場合、aを生成します。以下は、必要に応じて無効なインデックスをスキップします。

>>> b = [0,2,4,5]
>>> a = [0,1,2,3,4,5,6]
>>> [x for i,x in enumerate(a) if i in b]
[0, 2, 4, 5]
>>> b = [0,2,4,500]
>>> [x for i,x in enumerate(a) if i in b]
[0, 2, 4]

enumerateは、インデックスと値のペアのタプルを生成します。アイテムとそのインデックスの両方があるため、bのインデックスの存在を確認できます。

3
Brian

List Comprehension を使用すると、これは機能するはずです-

li = [a[i] for i in b]

これをテストする-

>>> a = [0,10,20,30,40,50,60]
>>> b = [0,2,4,5]
>>> li = [a[i] for i in b]
>>> li
[0, 20, 40, 50]
2
Kamehameha

numpy.asarrayを使用します。 Numpyでは、インデックスのリストによって配列の部分配列を取得できます。

>>> import numpy as np
>>> a = [0,10,20,30,40,50,60]
>>> b = [0,2,4,5]
>>> res = np.asarray(a)[b].tolist()
>>> res
[0, 20, 40, 50]
1
Temak

それがあなたにとって重要な場合のパフォーマンス向上のためのさらに別の選択肢-それは決して最もPython的ではありませんが、最も効率的であると確信しています:

>>> list(filter(lambda x: a.index(x) in b, a))
[0, 2, 4, 5]

注: Python 2.でlistに変換する必要はありません。ただし、Python 3以降(将来の訪問者に同様の問題が発生する可能性がある場合)。

1
Alex Thornton