web-dev-qa-db-ja.com

Pythonでそれを含むリストを与えられたアイテムのインデックスを見つける

リスト["foo", "bar", "baz"]とリスト"bar"内の項目の場合、Pythonでindex(1)を取得するにはどうすればよいですか?

2665
Eugene M
>>> ["foo", "bar", "baz"].index("bar")
1

参照: データ構造>リストの詳細

注意事項が続きます

これはおそらく質問に答える最も明快な方法ですが 尋ねられるように ですが、indexlist APIのかなり弱いコンポーネントであり、私が前回それを怒りで使ったのを覚えていることはできません。この答えは頻繁に参照されているので、より完全なものにすべきだというコメントで私は指摘されています。 list.indexに関するいくつかの注意点が続きます。そのためのdocstringを最初に見てみる価値があるでしょう。

>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.

リスト長の線形時間複雑性

index呼び出しは、一致するものが見つかるまで、リストのすべての要素を順番にチェックします。リストが長く、リスト内のどこにリストが表示されているかがおおまかにわからない場合は、この検索がボトルネックになる可能性があります。その場合は、別のデータ構造を検討する必要があります。マッチの場所をおおまかに知っていれば、indexにヒントを与えることができます。たとえば、このスニペットでは、l.index(999_999, 999_990, 1_000_000)はストレートl.index(999_999)よりもおよそ5桁速くなっています。前者は10エントリを検索するだけでよく、後者は100万件検索するからです。

>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514

引数に 最初に一致した のインデックスのみを返します

indexを呼び出すと、一致するものが見つかるまでリスト内を順番に検索し、 はそこで停止します。 より一致するインデックスが必要な場合は、リスト内包表記またはジェネレータ式を使用してください。

>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2

私がかつてindexを使っていたであろうところのほとんどの場所で、私は今リスト内包またはジェネレータ式を使います。 indexを手に入れることを考えているのであれば、これらの優れたPython機能を見てください。

要素がリストに存在しない場合にスローします

アイテムが存在しない場合、indexを呼び出すと、ValueErrorが返されます。

>>> [1, 1].index(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 2 is not in list

項目がリストに表示されていない可能性がある場合は、

  1. 最初にそれをitem in my_list(きれいで読みやすいアプローチ)でチェックする、または
  2. index呼び出しをValueErrorをキャッチするtry/exceptブロックでラップします(少なくとも検索するリストが長く、通常は項目が存在する場合はおそらく高速です)。
3853
Alex Coventry

Pythonを学ぶのに本当に役立つことの一つは、対話型ヘルプ機能を使うことです。

>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
 ...

 |
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value
 |

それはしばしばあなたが探している方法にあなたを導くでしょう。

833
davidavr

回答の大半は、 単一のインデックス を見つける方法を説明していますが、アイテムがリストに複数回含まれている場合、それらのメソッドは複数のインデックスを返しません。 enumerate() :を使用してください。

for i, j in enumerate(['foo', 'bar', 'baz']):
    if j == 'bar':
        print(i)

index()関数は最初の出現箇所のみを返し、enumerate()はすべての出現箇所を返します。

リスト内包として:

[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']

これは itertools.count() を使ったもう1つの小さな解決策です(これは列挙とほとんど同じ方法です)。

from itertools import izip as Zip, count # izip for maximum efficiency
[i for i, j in Zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']

これはenumerate()を使うよりも大きなリストに対してはより効率的です:

$ python -m timeit -s "from itertools import izip as Zip, count" "[i for i, j in Zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop
490
TerryA

すべてのインデックスを取得するには

 indexes = [i for i,x in enumerate(xs) if x == 'foo']
139
FMc

index() first の値のインデックスを返します。

|インデックス(...)
| L.index(value、[start、[stop]]) - > integer - 値の最初のインデックスを返す

def all_indices(value, qlist):
    indices = []
    idx = -1
    while True:
        try:
            idx = qlist.index(value, idx+1)
            indices.append(idx)
        except ValueError:
            break
    return indices

all_indices("foo", ["foo","bar","baz","foo"])
119
HongboZhu

要素がリストにない場合は問題が発生します。この機能は問題を処理します。

# if element is found it returns index of element else returns None

def find_element_in_list(element, list_element):
    try:
        index_element = list_element.index(element)
        return index_element
    except ValueError:
        return None
72
tanzil
a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']
65
savinson

検索している要素がリストにあるかどうかを確認するための条件を設定する必要があります

if 'your_element' in mylist:
    print mylist.index('your_element')
else:
    print None
46
user3670684

ここで提案されているすべての関数は固有の言語の振る舞いを再現していますが、何が起こっているのかをあいまいにしています。

[i for i in range(len(mylist)) if mylist[i]==myterm]  # get the indices

[each for each in mylist if each==myterm]             # get the items

mylist.index(myterm) if myterm in mylist else None    # get the first index and fail quietly

あなたの言語があなたが望むことをするための方法を提供するならば、なぜ例外処理で関数を書くのですか?

39
Graham Giller

すべてのインデックスが必要な場合は、 NumPy を使用できます。

import numpy as np

array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)

それは明確で読みやすい解決策です。

34
rbrisuda

Pythonでそれを含むリストを与えられたアイテムのインデックスを見つける

リスト["foo", "bar", "baz"]およびリスト"bar"内の項目について、Pythonでindex(1)を取得するための最もきれいな方法は何ですか?

確かに、最初に出現したインデックスを返すindexメソッドがあります。

>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1

この方法にはいくつか問題があります。

  • 値がリストにない場合はValueErrorが返されます
  • リストに複数の値が含まれている場合は、最初の値のインデックスのみが取得されます。

値なし

値が欠落している可能性がある場合は、ValueErrorをキャッチする必要があります。

あなたはこのような再利用可能な定義でそうすることができます:

def index(a_list, value):
    try:
        return a_list.index(value)
    except ValueError:
        return None

そしてこれを次のように使います。

>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1

そして、この欠点は、戻り値isまたはis not Noneがないかどうかを確認する必要があることです。

result = index(a_list, value)
if result is not None:
    do_something(result)

リスト内の複数の値

あなたがもっとオカレンスを持つことができるならば、あなたはnotlist.indexで完全な情報を得るでしょう:

>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1

あなたはインデックスをリスト内包に列挙することができます:

>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]

発生がない場合は、結果をブール値でチェックするか、結果をループしても何もしないでください。

indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
    do_something(index)

パンダを使ったデータの改良

パンダがある場合は、Seriesオブジェクトを使用してこの情報を簡単に入手できます。

>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object

比較チェックは一連のブール値を返します。

>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool

添字表記法を使用して、その一連のブール値をシリーズに渡すと、一致するメンバーだけが得られます。

>>> series[series == 'bar']
1    bar
3    bar
dtype: object

インデックスだけが必要な場合、index属性は一連の整数を返します。

>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')

そしてそれらをリストやTupleに入れたいのなら、コンストラクタに渡してください。

>>> list(series[series == 'bar'].index)
[1, 3]

はい、リスト内包表記を列挙型で使用することもできますが、私の考えではそれほどエレガントではありません - Cで書かれた組み込みコードに処理させるのではなく、Pythonで同等性のテストを行っています。

>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]

これは XY問題です

XY問題はあなたの実際の問題よりもむしろあなたの試みられた解決策について尋ねています。

なぜリストの要素に与えられたインデックスが必要だと思いますか?

あなたがすでにその値を知っているなら、なぜあなたはそれがリストのどこにあるかを気にかけますか?

値がそこにない場合、ValueErrorを捉えるのはかなり冗長です - そして私はそれを避けることを好みます。

とにかく私はたいていリストを反復処理しています、それで私はたいていどんな興味深い情報へのポインタも保ち、列挙で インデックスを得ます。

あなたがデータを管理しているのであれば、おそらくパンダを使うべきです - これは私が示した純粋なPythonの回避策よりはるかにエレガントなツールを持っています。

私はlist.indexを必要としていることを思い出しません。しかし、私はPythonの標準ライブラリを調べました、そして私はそれのためのいくつかの優れた用途を見ます。

idlelibには、GUIやテキストの解析のために、たくさんの用途があります。

keywordモジュールはそれを使用してモジュール内のコメントマーカーを見つけ、メタプログラミングを介してその中のキーワードのリストを自動的に再生成します。

Lib/mailbox.pyでは、順序付けられたマッピングのように使っているようです。

key_list[key_list.index(old)] = new

そして

del key_list[key_list.index(key)]

Lib/http/cookiejar.pyでは、翌月の入手に使用されているようです。

mon = MONTHS_LOWER.index(mon.lower())+1

Lib/tarfile.pyではdistutilsと似ていて、項目までスライスすることができます。

members = members[:members.index(tarinfo)]

Lib/pickletools.pyでは、

numtopop = before.index(markobject)

これらの用法が共通しているように見えるのは、それらが(O(n) list.indexのルックアップ時間のために重要な)制限されたサイズのリストで動作するように見えることですアイドルの場合).

それのためのユースケースがありますが、それらはかなり珍しいです。この答えを探しているのであれば、あなたがしていることがあなたのユースケースのために言語によって提供されるツールの最も直接的な使用法であるかどうか自分自身に尋ねなさい。

25
Aaron Hall

Zip 関数を持つすべてのインデックス:

get_indexes = lambda x, xs: [i for (y, i) in Zip(xs, range(len(xs))) if x == y]

print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')

リスト内の1つ以上の(同一の)項目の出現回数と位置をすべて取得する

Enumerate(alist)を使うと、要素xが探しているものと等しいとき、リストのインデックスである最初の要素(n)を保存することができます。

>>> alist = ['foo', 'spam', 'Egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>

関数findindexを作りましょう

この関数は、項目とリストを引数として取り、前に見たようにリスト内の項目の位置を返します。

def indexlist(item2find, list_or_string):
  "Returns all indexes of an item in a list or a string"
  return [n for n,item in enumerate(list_or_string) if item==item2find]

print(indexlist("1", "010101010"))

出力


[1, 3, 5, 7]

単純な

for n, i in enumerate([1, 2, 3, 4, 1]):
    if i == 1:
        print(n)

出力:

0
4
16
Giovanni Gianni

そして今、完全に異なるもののために...

...インデックスを取得する前にアイテムの存在を確認するようなものです。このアプローチの素晴らしい点は、空のリストであっても、関数は常にインデックスのリストを返すことです。文字列でも動作します。

def indices(l, val):
    """Always returns a list containing the indices of val in the_list"""
    retval = []
    last = 0
    while val in l[last:]:
            i = l[last:].index(val)
            retval.append(last + i)
            last += i + 1   
    return retval

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')

インタラクティブなpythonウィンドウに貼り付けた場合:

Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(the_list, val):
...     """Always returns a list containing the indices of val in the_list"""
...     retval = []
...     last = 0
...     while val in the_list[last:]:
...             i = the_list[last:].index(val)
...             retval.append(last + i)
...             last += i + 1   
...     return retval
... 
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>> 

更新

ヘッドダウンpython開発の1年後、私は元の答えに少し恥ずかしく思います。そのため、記録をまっすぐにするには、上記のコードを使用できます。ただし、同じ動作を得るためのmuchより慣用的な方法は、enumerate()関数とともにリスト内包表記を使用することです。

このようなもの:

def indices(l, val):
    """Always returns a list containing the indices of val in the_list"""
    return [index for index, value in enumerate(l) if value == val]

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')

インタラクティブなpythonウィンドウに貼り付けると、次のようになります。

Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 11:07:58) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(l, val):
...     """Always returns a list containing the indices of val in the_list"""
...     return [index for index, value in enumerate(l) if value == val]
... 
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>> 

そして今、この質問とすべての答えを検討した後、これがまさに FMc が彼の 以前の答え で示唆したものであることに気付きました。私が最初にこの質問に答えたとき、私はそれを理解していなかったので、その答えさえ見ませんでした。私のやや冗長な例が理解を助けることを願っています。

上記の1行のコードがまだ意味をなさない場合、Googleの「Pythonリスト内包表記」を強くお勧めします。慣れてください。これは、コードを開発するためにPythonを使用することを喜びにする多くの強力な機能の1つにすぎません。

15
MrWonderful

ただ一緒に行くことができます

a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']

res = [[x[0] for x in a].index(y) for y in b]
15
kiriloff

別のオプション

>>> a = ['red', 'blue', 'green', 'red']
>>> b = 'red'
>>> offset = 0;
>>> indices = list()
>>> for i in range(a.count(b)):
...     indices.append(a.index(b,offset))
...     offset = indices[-1]+1
... 
>>> indices
[0, 3]
>>> 
15

FMcとuser7177からの答えの変形は、あらゆるエントリのすべてのインデックスを返すことができる辞書を与えるでしょう:

>>> a = ['foo','bar','baz','bar','any', 'foo', 'much']
>>> l = dict(Zip(set(a), map(lambda y: [i for i,z in enumerate(a) if z is y ], set(a))))
>>> l['foo']
[0, 5]
>>> l ['much']
[6]
>>> l
{'baz': [2], 'foo': [0, 5], 'bar': [1, 3], 'any': [4], 'much': [6]}
>>> 

これを1つのエントリのすべてのインデックスを取得するための1つのライナーとして使用することもできます。効率の保証はありませんが、ラムダが呼び出される回数を減らすためにset(a)を使用しました。

13
bvanlew

この解決法は他のものほど強力ではありませんが、あなたが初心者でforloopsについてだけ知っているのであればValueErrorを避けながらアイテムの最初のインデックスを見つけることはまだ可能です:

def find_element(p,t):
    i = 0
    for e in p:
        if e == t:
            return i
        else:
            i +=1
    return -1
10
dylankb

Pythonリストはゼロから始まるので、Zip組み込み関数を次のように使用できます。

>>> [i for i,j in Zip(range(len(haystack)), haystack) if j == 'needle' ]

"haystack"は問題のリストで、 "needle"は探す項目です。

(注:ここでは、インデックスを取得するためにiを使用して繰り返していますが、アイテムに焦点を合わせる必要がある場合は、jに切り替えることができます。)

5
jihed gasmi
name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
    new_list.append(item[0])
print(new_list)
try:
    location= new_list.index(name)
except:
    location=-1
print (location)

これは、文字列もリストに含まれていない場合は考慮され、リストに含まれていない場合はlocation = -1になります。

5
Coder123

リストLの項目xのインデックスを見つける:

idx = L.index(x) if (x in L) else -1
4
Ketan

リストに繰り返し項目がない場合は、インデックスを確認する必要があります。

 eg: li=[10,20,30] # here need to get index of 20 means
     li.index(20) # will work properly because 20 is not repeated

繰り返しても最初のインデックスしか表示されない

アイテムが存在するすべてのインデックスを取得する必要がある場合

eg: li=[10,20,30,20,40, 50, 10] # here need to get index of 20 means its have 2 index (1,3) 

あなたがそれをする必要があることを得るために

 li=[10,20,30,20,40, 50, 10]
 [i for i, e in enumerate(li) if e == 20]

[1,3]のようにo/pとしてインデックスのリストを取得します。

3
abhi krishnan

これに対するもっと機能的な答えがあります。

list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))

より一般的な形式:

def get_index_of(lst, element):
    return list(map(lambda x: x[0],\
       (list(filter(lambda x: x[1]==element, enumerate(lst))))))
3
Ankit Gupta

アイテムが見つからなかった場合、Pythonのindex()メソッドはエラーをスローします。

そのため、代わりに、アイテムが見つからなかった場合に-1を返すJavaScriptのindexOf()関数に似たものにすることができます。

    try:
        index = array.index('search_keyword')
    except ValueError:
        index = -1
3
Hamed Baatour

リストにlstという名前を付けましょう。リストlstnumpy arrayに変換することができます。そして、 numpy.where を使用して、リスト内の選択した項目のインデックスを取得します。実装方法は次のとおりです。

import numpy as np

lst = ["foo", "bar", "baz"]  #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]

>>> 1
2

@TerryAで示されるように、one indexを見つける方法について多くの回答が話し合っています。

more_itertoolsmultipleインデックスをイテラブル内で検索するためのツールを備えたサードパーティのライブラリです。

与えられた

import more_itertools as mit


iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]

コード

複数の観測値のインデックスを見つける:

list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]

複数の項目をテストする:

list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]

more_itertools.locate の他のオプションも参照してください。 > pip install more_itertools からインストールしてください。

2
pylang

私のような他の言語から来た人たちにとっては、たぶん簡単なループで理解して使うのが簡単でしょう:

mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
  if item == "bar":
    print(index, item)

に感謝します。それで、正確に列挙は何をするのでしょうか?。それは私が理解するのを助けました。

1
mpoletto

パフォーマンスが問題になる場合:

list.index(item)メソッドの組み込みメソッドはO(n)アルゴリズムであることが多くの回答で言及されています。あなたがこれを一度実行する必要があればそれは結構です。しかし、要素のインデックスに何度もアクセスする必要がある場合は、最初にアイテムとインデックスのペアの辞書(O(n))を作成し、次にO(1)のインデックスにアクセスするほうが合理的です。あなたがそれを必要とするたびに。

リスト内の項目が繰り返されないことが確実な場合は、簡単に次のことができます。

myList = ["foo", "bar", "baz"]

# Create the dictionary
myDict = dict((e,i) for i,e in enumerate(myList))

# Lookup
myDict["bar"] # Returns 1
# myDict.get("blah") if you don't want an error to be raised if element not found.

重複した要素があり、それらのすべてのインデックスを返す必要がある場合は、次の手順を実行します。

from collections import defaultdict as dd
myList = ["foo", "bar", "bar", "baz", "foo"]

# Create the dictionary
myDict = dd(list)
for i,e in enumerate(myList):
    myDict[e].append(i)

# Lookup
myDict["foo"] # Returns [0, 4]
1
FatihAkici

辞書を使用して、ここで最初にリストを処理してからそれにインデックスを追加します

from collections import defaultdict

index_dict = defaultdict(list)    
Word_list =  ['foo','bar','baz','bar','any', 'foo', 'much']

for Word_index in range(len(Word_list)) :
    index_dict[Word_list[Word_index]].append(Word_index)

Word_index_to_find = 'foo'       
print(index_dict[Word_index_to_find])

# output :  [0, 5]
0
prashant rana