Pertanyaan Menemukan indeks dari suatu item yang diberikan daftar yang mengandung itu dengan Python


Untuk daftar ["foo", "bar", "baz"] dan sebuah item dalam daftar "bar", bagaimana saya mendapatkan indeksnya (1) dengan Python?


2238
2017-10-07 01:39


asal


Jawaban:


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

Referensi: Struktur Data> Lainnya di Daftar

Peringatan diikuti

Perhatikan bahwa ini mungkin cara paling bersih untuk menjawab pertanyaan seperti yang diminta, index adalah komponen yang agak lemah list API, dan saya tidak ingat kapan terakhir kali saya menggunakannya dalam kemarahan. Sudah ditunjukkan kepada saya di komentar bahwa karena jawaban ini sangat dirujuk, itu harus dibuat lebih lengkap. Beberapa peringatan tentang list.index mengikuti. Mungkin awalnya layak untuk melihat di docstring untuk itu:

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

Lini waktu-kompleksitas dalam daftar panjang

Sebuah index panggil memeriksa setiap elemen dari daftar secara berurutan, sampai menemukan kecocokan. Jika daftar Anda panjang, dan Anda tidak tahu secara kasar di mana dalam daftar itu terjadi, pencarian ini bisa menjadi hambatan. Dalam hal ini, Anda harus mempertimbangkan struktur data yang berbeda. Perhatikan bahwa jika Anda tahu kira-kira di mana menemukan pertandingan, Anda bisa memberi index petunjuk. Misalnya, dalam cuplikan ini, l.index(999_999, 999_990, 1_000_000) kira-kira lima lipat lebih cepat daripada lurus l.index(999_999), karena yang pertama hanya harus mencari 10 entri, sementara yang terakhir mencari satu juta:

>>> 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

Hanya mengembalikan indeks dari pertandingan pertama untuk argumennya

Panggilan ke index mencari melalui daftar dalam urutan hingga menemukan kecocokan, dan berhenti di sana. Jika Anda mengharapkan perlu indeks lebih banyak kecocokan, Anda harus menggunakan pemahaman daftar, atau ekspresi generator.

>>> [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

Sebagian besar tempat di mana saya pernah digunakan index, Saya sekarang menggunakan pemahaman daftar atau ekspresi generator karena mereka lebih dapat digeneralisasikan. Jadi jika Anda mempertimbangkan meraih index, lihat fitur-fitur python yang luar biasa ini.

Melempar jika elemen tidak ada dalam daftar

Panggilan ke index hasil dalam ValueError jika barangnya tidak ada.

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

Jika item tersebut mungkin tidak ada dalam daftar, Anda juga harus

  1. Periksa dulu dengan item in my_list (pendekatan bersih, mudah dibaca), atau
  2. Bungkus index panggilan masuk a try/except blok yang menangkap ValueError (mungkin lebih cepat, setidaknya ketika daftar untuk pencarian panjang, dan item biasanya ada.)

3299
2017-10-07 01:40



Satu hal yang sangat membantu dalam mempelajari Python adalah menggunakan fungsi bantuan interaktif:

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

class list(object)
 ...

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

yang akan sering mengarahkan Anda ke metode yang Anda cari.


785
2017-10-07 13:19



Mayoritas jawaban menjelaskan cara menemukannya satu indeks, tetapi metode mereka tidak mengembalikan beberapa indeks jika item tersebut ada dalam daftar beberapa kali. Menggunakan enumerate():

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

Itu index() fungsi hanya mengembalikan kejadian pertama, sementara enumerate() mengembalikan semua kejadian.

Sebagai pemahaman daftar:

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

Ini juga solusi kecil lainnya itertools.count() (yang cukup banyak pendekatan yang sama dengan enumerate):

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

Ini lebih efisien untuk daftar yang lebih besar daripada menggunakan 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

446
2018-06-19 22:31



Untuk mendapatkan semua indeks:

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

123
2018-06-25 15:07



index()mengembalikan pertama indeks nilai!

| indeks(...)
   | L.index (value, [start, [stop]]) -> integer - kembalikan nilai indeks pertama

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"])

105
2017-08-30 09:40



Suatu masalah akan muncul jika elemen tersebut tidak ada dalam daftar. Fungsi ini menangani masalah:

# 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

67
2018-04-16 10:19



a = ["foo","bar","baz",'bar','any','much']

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

57
2017-08-21 12:01



Anda harus menetapkan syarat untuk memeriksa apakah elemen yang Anda cari ada dalam daftar

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

39
2018-05-26 04:26



Semua fungsi yang diusulkan di sini mereproduksi perilaku bahasa yang melekat tetapi mengaburkan apa yang terjadi.

[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

Mengapa menulis fungsi dengan penanganan eksepsi jika bahasa menyediakan metode untuk melakukan apa yang Anda inginkan sendiri?


34
2018-05-16 16:45



Jika Anda menginginkan semua indeks, maka Anda bisa menggunakannya 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),)

Ini jelas, solusi yang mudah dibaca.


27
2017-11-17 19:05



Menemukan indeks dari suatu item yang diberikan daftar yang mengandung itu dengan Python

Untuk daftar ["foo", "bar", "baz"] dan sebuah item dalam daftar "bar", apa cara terbersih untuk mendapatkan indeksnya (1) dengan Python?

Yah, tentu, ada metode indeks, yang mengembalikan indeks kejadian pertama:

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

Ada beberapa masalah dengan metode ini:

  • jika nilainya tidak ada dalam daftar, Anda akan mendapatkan ValueError
  • jika lebih dari satu nilai ada dalam daftar, Anda hanya mendapatkan indeks untuk yang pertama

Tidak ada nilai

Jika nilainya bisa hilang, Anda harus menangkapnya ValueError.

Anda dapat melakukannya dengan definisi yang dapat digunakan kembali seperti ini:

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

Dan gunakan seperti ini:

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

Dan sisi buruknya adalah Anda mungkin akan memeriksanya jika nilai yang dikembalikan is atau is not Tidak ada:

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

Lebih dari satu nilai dalam daftar

Jika Anda bisa memiliki lebih banyak kejadian, Anda akan tidak dapatkan informasi lengkap dengan list.index:

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

Anda mungkin menghitung ke dalam daftar pemahaman indeks:

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

Jika Anda tidak memiliki kemunculan, Anda dapat memeriksanya dengan pemeriksaan boolean dari hasil, atau hanya tidak melakukan apa pun jika Anda mengulang hasilnya:

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

Lebih baik data munging dengan panda

Jika Anda memiliki panda, Anda dapat dengan mudah mendapatkan informasi ini dengan objek Seri:

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

Cek perbandingan akan mengembalikan serangkaian boolean:

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

Lewatkan seri boolean ke seri melalui notasi subscript, dan Anda hanya mendapatkan anggota yang cocok:

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

Jika Anda hanya menginginkan indeks, atribut indeks mengembalikan serangkaian bilangan bulat:

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

Dan jika Anda menginginkannya dalam daftar atau tupel, cukup lewati saja ke konstruktor:

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

Ya, Anda bisa menggunakan daftar pemahaman dengan menghitung juga, tapi itu tidak begitu elegan, menurut pendapat saya - Anda melakukan tes untuk kesetaraan dengan Python, bukannya membiarkan kode builtin ditulis dalam C menanganinya:

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

Apakah ini sebuah Masalah XY?

Masalah XY bertanya tentang solusi yang Anda coba daripada masalah Anda yang sebenarnya.

Menurut Anda, mengapa Anda membutuhkan indeks yang diberikan elemen dalam daftar?

Jika Anda sudah tahu nilainya, mengapa Anda peduli di mana itu ada dalam daftar?

Jika nilainya tidak ada, tangkap ValueError agak verbose - dan saya lebih suka menghindari itu.

Saya biasanya iterasi atas daftar anyways, jadi saya biasanya akan menyimpan pointer ke informasi menarik, mendapatkan indeks dengan menyebutkan.

Jika Anda mem-pash data, Anda mungkin harus menggunakan panda - yang memiliki alat yang jauh lebih elegan daripada solusi Python murni yang pernah saya tunjukkan.

Saya tidak ingat membutuhkan list.indexsaya sendiri. Namun, saya telah melihat melalui pustaka standar Python, dan saya melihat beberapa kegunaan yang sangat baik untuk itu.

Ada banyak, banyak kegunaan untuk itu idlelib, untuk GUI dan penguraian teks.

Itu keyword modul menggunakannya untuk mencari penanda komentar dalam modul untuk secara otomatis meregenerasi daftar kata kunci di dalamnya melalui metaprogramming.

Di Lib / mailbox.py tampaknya menggunakannya seperti pemetaan yang dipesan:

key_list[key_list.index(old)] = new

dan

del key_list[key_list.index(key)]

Di Lib / http / cookiejar.py, tampaknya digunakan untuk mendapatkan bulan berikutnya:

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

Di Lib / tarfile.py mirip dengan distutils untuk mendapatkan potongan ke item:

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

Di Lib / pickletools.py:

numtopop = before.index(markobject)

Apa yang tampaknya memiliki kesamaan ini adalah bahwa mereka tampaknya beroperasi pada daftar ukuran terbatas (penting karena O (n) waktu pencarian untuk list.index), dan sebagian besar digunakan dalam parsing (dan UI dalam kasus Idle).

Meskipun ada kasus penggunaan untuk itu, mereka cukup tidak umum. Jika Anda menemukan diri Anda mencari jawaban ini, tanyakan pada diri Anda apakah yang Anda lakukan adalah penggunaan alat-alat yang paling langsung disediakan oleh bahasa untuk kasus penggunaan Anda.


22
2017-08-22 03:08