リスト["foo", "bar", "baz"]
とリスト内のアイテムが与えられた場合、Pythonで"bar"
そのインデックス(1
)を取得するにはどうすればよいですか?
リスト["foo", "bar", "baz"]
とリスト内のアイテムが与えられた場合、Pythonで"bar"
そのインデックス(1
)を取得するにはどうすればよいですか?
回答:
>>> ["foo", "bar", "baz"].index("bar")
1
リファレンス:データ構造>リストの詳細
これはおそらく、質問に答えるためのクリーンな方法である一方であること注尋ねたとして、index
のかなり弱い部品であるlist
API、そして私は、私は怒りでそれを使用した最後の時間を思い出すことができません。この回答は頻繁に参照されているため、より完全にする必要があるというコメントで指摘されました。list.index
フォローに関するいくつかの注意事項。おそらく最初にそのドキュメントを見てみる価値があります。
list.index(x[, start[, end]])
値がxに等しい最初の項目のリストでゼロから始まるインデックスを返します。
ValueError
そのようなアイテムがない場合はaを発生させます。オプションの引数startおよびendはスライス表記と同様に解釈され、検索をリストの特定のサブシーケンスに制限するために使用されます。返されるインデックスは、開始引数ではなく、シーケンス全体の先頭を基準にして計算されます。
index
それが一致するものが見つかるまで呼び出しは、順番にリストのすべての要素をチェックします。リストが長く、リストのどこで発生するかがおおよそわからない場合、この検索がボトルネックになる可能性があります。その場合は、別のデータ構造を検討する必要があります。一致する場所を大まかに知っている場合はindex
、ヒントを与えることができます。たとえば、このスニペットでl.index(999_999, 999_990, 1_000_000)
はl.index(999_999)
、前者は10個のエントリを検索するだけでよく、後者は100万個を検索するので、ストレートよりもおよそ5桁高速です。
>>> 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
aにValueError
なります。
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
アイテムがリストにない場合は、次のいずれかを行う必要があります
item in my_list
(クリーンで読みやすいアプローチ)、またはindex
するtry/except
ブロックで呼び出しをラップしますValueError
(おそらくより高速で、少なくとも検索するリストが長く、アイテムが通常存在する場合)。index()
、整数のリストに対するリストの理解よりも90%ほど高速であることがわかりました。
Pythonの学習に本当に役立つ1つのことは、対話型ヘルプ機能を使用することです。
>>> help(["foo", "bar", "baz"])
Help on list object:
class list(object)
...
|
| index(...)
| L.index(value, [start, [stop]]) -> integer -- return first index of value
|
多くの場合、あなたが探している方法にたどり着きます。
回答の大部分は単一のインデックスを見つける方法を説明していますが、それらのメソッドは、アイテムがリストに複数回ある場合、複数のインデックスを返しません。使用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()
(これは列挙とほぼ同じアプローチです):
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
すべてのインデックスを取得するには:
indexes = [i for i,x in enumerate(xs) if x == 'foo']
index()
値の最初のインデックスを返します!
| index(...)
| 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"])
a = ["foo","bar","baz",'bar','any','much']
indexes = [index for index in range(len(a)) if a[index] == 'bar']
検索する要素がリストにあるかどうかを確認する条件を設定する必要があります
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
ここで提案されている関数はすべて、固有の言語動作を再現しますが、何が起こっているのかはわかりません。
[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
言語があなた自身がやりたいことをするメソッドを提供しているのに、なぜ例外処理付きの関数を書くのですか?
すべてのインデックスが必要な場合は、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),)
明確で読みやすいソリューションです。
Pythonでアイテムを含むリストを指定してアイテムのインデックスを見つける
リスト
["foo", "bar", "baz"]
とリスト内のアイテムについて、"bar"
Pythonでそのインデックス(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)
さらに多く発生する可能性がある場合、次のコマンドでは完全な情報を取得できませんlist.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')
そして、それらをリストまたはタプルに入れたい場合は、コンストラクタに渡してください:
>>> list(series[series == 'bar'].index)
[1, 3]
はい、リスト内包表記を列挙と一緒に使用することもできますが、私の意見では、それほどエレガントではありません-Cで記述された組み込みコードに処理を任せる代わりに、Pythonで同等性のテストを行っています。
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
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
distutilsに似たLib / tarfile.pyで、アイテムまでのスライスを取得します。
members = members[:members.index(tarinfo)]
Lib / pickletools.pyで:
numtopop = before.index(markobject)
これらの使用法に共通しているように見えるのは、制約されたサイズのリスト(O(n)のルックアップ時間のために重要)を操作しているように見えlist.index
、解析(およびIdleの場合はUI)で主に使用されていることです。
それのユースケースはありますが、それらはかなりまれです。この答えを探している場合は、使用している言語で提供されているツールを最も直接使用しているのかどうかを自問してください。
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')
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]
>>>
この関数は引数としてアイテムとリストを取り、前に見たようにリスト内のアイテムの位置を返します。
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
別のオプション
>>> 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]
>>>
...インデックスを取得する前にアイテムの存在を確認するようなものです。このアプローチの良い点は、関数が常にインデックスのリストを返すことです-空のリストであっても。文字列でも動作します。
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]
>>>
もう1年間ヘッズダウンでPythonを開発した後、元の答えに少し困惑したので、記録を正直に設定するには、上記のコードを使用できます。しかし、多くの同じ動作を取得するために、より慣用的な方法は、列挙()関数と一緒に、リストの内包表記を使用することです。
このようなもの:
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つにすぎません。
FMcおよびuser7177からの回答のバリアントは、任意のエントリのすべてのインデックスを返すことができるdictを提供します。
>>> 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)を使用しましたが、効率の保証はありません。
Pythonリストはゼロベースであるため、次のようにzip組み込み関数を使用できます。
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
ここで、「haystack」は問題のリストであり、「needle」は検索する項目です。
(注:ここでは、インデックスを取得するためにiを使用して反復していますが、アイテムに集中する必要がある場合は、jに切り替えることができます。)
index()
アイテムが見つからなかった場合、Python メソッドはエラーをスローします。そのため、代わりに、アイテムが見つからなかった場合indexOf()
に返さ-1
れるJavaScript の関数のようにすることができます。
try:
index = array.index('search_keyword')
except ValueError:
index = -1
これにはより機能的な答えがあります。
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))))))
Scala
/ 機能プログラミング愛好家
lst
持っているリストに名前を付けましょう。リストlst
をに変換できnumpy 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
私のような別の言語から来ている人にとっては、おそらく単純なループを使用すると、それを理解して使用する方が簡単です:
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
私は感謝していますそれで、列挙は正確に何をしますか?。それは私が理解するのに役立ちました。
インデックスを一度検索する場合は、「インデックス」メソッドを使用するのが適切です。ただし、データを複数回検索する場合は、bisectモジュールの使用をお勧めします。bisectモジュールを使用すると、データをソートする必要があることに注意してください。したがって、データを1回ソートすると、bisectを使用できます。使用二分私のマシン上のモジュールは、より高速なインデックスメソッドを使用するよりも20倍程度です。
Python 3.8以上の構文を使用したコードの例を次に示します。
import bisect
from timeit import timeit
def bisect_search(container, value):
return (
index
if (index := bisect.bisect_left(container, value)) < len(container)
and container[index] == value else -1
)
data = list(range(1000))
# value to search
value = 666
# times to test
ttt = 1000
t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)
print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")
出力:
t1=0.0400, t2=0.0020, diffs t1/t2=19.60
メソッドの組み込みlist.index(item)
メソッドはO(n)アルゴリズムであると多くの回答で言及されています。これを1回実行する必要がある場合は問題ありません。ただし、要素のインデックスに何度もアクセスする必要がある場合は、最初に項目とインデックスのペアのディクショナリ(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]
@TerryAで示されているように、1つのインデックスを見つける方法については多くの回答で議論されています。
more_itertools
イテラブル内の複数のインデックスを見つけるためのツールを備えたサードパーティのライブラリです。
与えられた
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
ます。
辞書を使用して、リストを最初に処理し、次にインデックスを追加します
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]
私の意見で["foo", "bar", "baz"].index("bar")
は、それは良いですが、それは十分ではありません!「bar」が辞書にない場合、ValueError
発生するので、この関数を使うことができます:
def find_index(arr, name):
try:
return arr.index(name)
except ValueError:
return -1
if __name__ == '__main__':
print(find_index(["foo", "bar", "baz"], "bar"))
結果は次のとおりです。
1
nameがarrになかった場合、関数は-1を返します。次に例を示します。
print(find_index(["foo"、 "bar"、 "baz"]、 "fooo"))
-1
l = [1, 2]; find_index(l, 3)
戻り-1
、l[find_index(l, 3)]
が戻るため、これを使用しないでください2
。-1を返すのは悪いことです。Noneを返すだけです。
"bar"
、[2]すべてのインデックス"bar"
?