web-dev-qa-db-ja.com

python)内のリストまたは文字列の連続しない要素へのアクセス

私の知る限り、これは公式には不可能ですが、スライスによってリストの任意の非順次要素にアクセスするための「トリック」はありますか?

例えば:

>>> L = range(0,101,10)
>>> L
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

今、できるようになりたい

a,b = L[2,5]

そのため a == 20およびb == 50

2つのステートメント以外の1つの方法は、次のようなばかげたものになります。

a,b = L[2:6:3][:2]

しかし、それは不規則な間隔にはまったく対応していません。

たぶん、私が欲しいインデックスを使ったリスト内包表記で?

[L[x] for x in [2,5]]

この一般的な問題に対して何が推奨されるのか知りたいです。

22
beroe

このようなもの?

def select(lst, *indices):
    return (lst[i] for i in indices)

使用法:

>>> def select(lst, *indices):
...     return (lst[i] for i in indices)
...
>>> L = range(0,101,10)
>>> a, b = select(L, 2, 5)
>>> a, b
(20, 50)

関数が機能する方法は、 ジェネレーターオブジェクト を返すことです。これは、あらゆる種類のPythonシーケンスと同様に繰り返すことができます。

コメントで@justhalfが指摘しているように、呼び出し構文は、関数パラメーターを定義する方法によって変更できます。

def select(lst, indices):
    return (lst[i] for i in indices)

そして、次のようにして関数を呼び出すことができます。

select(L, [2, 5])

または任意のリスト。

更新:ジェネレーターの遅延評価機能が本当に必要でない限り、代わりにoperator.itemgetterを使用することをお勧めします。 ジョンYの答え を参照してください。

9
Shashank

おそらくあなたが探しているものに最も近いのは itemgetter (または ここ for Python 2 docs):

>>> L = list(range(0, 101, 10))  # works in Python 2 or 3
>>> L
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
>>> from operator import itemgetter
>>> itemgetter(2, 5)(L)
(20, 50)
26
John Y

numpyを使用できる場合は、次のようにすることができます。

>>> import numpy
>>> the_list = numpy.array(range(0,101,10))
>>> the_indices = [2,5,7]
>>> the_subset = the_list[the_indices]
>>> print the_subset, type(the_subset)
[20 50 70] <type 'numpy.ndarray'>
>>> print list(the_subset)
[20, 50, 70]

numpy.arraylistと非常によく似ていますが、数学演算や、ここに示すような任意のインデックス選択など、より多くの演算をサポートしているだけです。

11
justhalf

完全を期すために、元の質問の方法は非常に単純です。 Lが関数自体である場合は、関数でラップするか、関数の結果を事前に変数に割り当てて、繰り返し呼び出されないようにします。

[L[x] for x in [2,5]]

もちろん、文字列でも機能します...

["ABCDEF"[x] for x in [2,0,1]]
['C', 'A', 'B']
4
beroe

他の答えはどれも 多次元オブジェクト スライスでは機能しません。私見これは最も一般的な解決策です(numpyを使用):

numpy.ix_ は、配列のすべての次元で任意のインデックスを同時に選択できます。

例えば。:

>>> a = np.arange(10).reshape(2, 5) # create an array
>>> a
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> ixgrid = np.ix_([0, 1], [2, 4]) # create the slice-like grid
>>> ixgrid
(array([[0],
       [1]]), array([[2, 4]]))
>>> a[ixgrid]                       # use the grid to slice a
array([[2, 4],
       [7, 9]])
1
Jesse Knight