2.5k

Đối với một danh sách ["foo", "bar", "baz"]và một mục trong danh sách "bar", làm cách nào để lấy chỉ mục của nó (1) trong Python?

|
  • 3

    Bạn có quay lại không: [1] Chỉ số thấp nhất trong trường hợp có nhiều trường hợp "bar", [2] Tất cả các chỉ số của "bar"?

    – Huỳnh Thu Bích 20:56:39 12/05/2018
  • 2

    a) Có đảm bảo rằng mục đó có trong danh sách không, nếu không chúng ta nên xử lý trường hợp lỗi như thế nào? (trả về Không / tăng ValueError) b) Các mục trong danh sách có được đảm bảo là duy nhất không và chúng tôi có nên trả về chỉ mục đầu tiên của trận đấu hoặc tất cả các chỉ mục không?

    – Phạm Tuấn Hùng 06:20:46 21/05/2018
3.8k
>>> ["foo", "bar", "baz"].index("bar")
1

Tham khảo: Cấu trúc dữ liệu> Thêm về danh sách

Hãy cẩn thận

Lưu ý rằng mặc dù đây có lẽ là cách sạch nhất để trả lời câu hỏi khi được hỏi , indexlà một thành phần khá yếu của listAPI và tôi không thể nhớ lần cuối cùng tôi sử dụng nó trong sự tức giận. Nó đã được chỉ ra cho tôi trong các ý kiến ​​rằng vì câu trả lời này được tham khảo nhiều, nên nó cần được thực hiện đầy đủ hơn. Một số hãy cẩn thận về sau list.index. Có lẽ ban đầu đáng để xem qua chuỗi tài liệu cho nó:

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

Độ phức tạp thời gian tuyến tính trong chiều dài danh sách

Một indexcuộc gọi kiểm tra mọi yếu tố của danh sách theo thứ tự, cho đến khi tìm thấy kết quả khớp. Nếu danh sách của bạn dài và bạn không biết đại khái là nơi nào trong danh sách đó, tìm kiếm này có thể trở thành nút cổ chai. Trong trường hợp đó, bạn nên xem xét một cấu trúc dữ liệu khác nhau. Lưu ý rằng nếu bạn biết đại khái nơi tìm trận đấu, bạn có thể đưa ra indexgợi ý. Chẳng hạn, trong đoạn trích này, l.index(999_999, 999_990, 1_000_000)nhanh hơn khoảng năm bậc so với đường thẳng l.index(999_999), bởi vì cái trước chỉ phải tìm kiếm 10 mục, trong khi cái sau tìm kiếm một triệu:

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

Chỉ trả về chỉ mục của trận đấu đầu tiên cho đối số của nó

Một cuộc gọi để indextìm kiếm thông qua danh sách theo thứ tự cho đến khi tìm thấy kết quả khớp và dừng ở đó. Nếu bạn muốn có các chỉ số của nhiều kết quả khớp hơn, bạn nên sử dụng cách hiểu danh sách hoặc biểu thức trình tạo.

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

Hầu hết các địa điểm mà trước đây tôi từng sử dụng index, giờ đây tôi sử dụng biểu thức hiểu danh sách hoặc biểu thức trình tạo vì chúng có tính khái quát cao hơn. Vì vậy, nếu bạn đang xem xét tiếp cận index, hãy xem các tính năng tuyệt vời này của trăn.

Ném nếu phần tử không có trong danh sách

Một cuộc gọi để indexkết quả trong một ValueErrornếu mặt hàng không có mặt.

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

Nếu mục này có thể không có trong danh sách, bạn nên

  1. Trước tiên hãy kiểm tra nó bằng item in my_list(cách tiếp cận rõ ràng, dễ đọc) hoặc
  2. Kết thúc indexcuộc gọi trong một try/exceptkhối bắt ValueError(có thể nhanh hơn, ít nhất là khi danh sách cần tìm kiếm dài và mục này thường có mặt.)
|
829

Một điều thực sự hữu ích khi học Python là sử dụng chức năng trợ giúp tương tác:

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

class list(object)
 ...

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

mà thường sẽ dẫn bạn đến phương pháp bạn đang tìm kiếm.

|
483

Phần lớn các câu trả lời giải thích cách tìm một chỉ mục , nhưng các phương thức của chúng không trả về nhiều chỉ mục nếu mục đó nằm trong danh sách nhiều lần. Sử dụng enumerate():

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

Các index()chức năng chỉ trả về sự xuất hiện đầu tiên, trong khi enumerate()trả về tất cả các lần xuất hiện.

Như một sự hiểu biết danh sách:

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

Đây cũng là một giải pháp nhỏ khác với itertools.count()(cách tiếp cận khá giống với cách liệt kê):

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

Điều này hiệu quả hơn cho các danh sách lớn hơn so với sử dụng 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
|
  • 1

    Phép liệt kê hoạt động tốt hơn các phương thức dựa trên chỉ mục đối với tôi, vì tôi đang tìm cách thu thập các chỉ số của chuỗi bằng cách sử dụng 'startedwith "và tôi cần thu thập nhiều lần xuất hiện. Hoặc có cách nào để sử dụng chỉ mục với" startedwith "mà tôi không thể tìm ra

    – Trịnh Long Giang 19:15:53 26/10/2017
  • 1

    Trong tay tôi, phiên bản liệt kê luôn nhanh hơn một chút. Một số chi tiết thực hiện có thể đã thay đổi kể từ khi phép đo ở trên được đăng.

    – Đỗ Hồng Tâm 18:43:32 17/11/2017
  • 1

    Điều này đã được trả lời kể từ '11: stackoverflow.com/questions/6294179/ cấp

    – Ngo Hang 10:55:37 10/02/2019
139

Để có được tất cả các chỉ mục:

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

index()trả về chỉ số đầu tiên của giá trị!

| chỉ mục (...)
| L.index (giá trị, [bắt đầu, [dừng]]) -> số nguyên - trả về chỉ số đầu tiên của giá trị

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

Một vấn đề sẽ phát sinh nếu phần tử không có trong danh sách. Hàm này xử lý vấn đề:

# 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
|
65
a = ["foo","bar","baz",'bar','any','much']

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

Bạn phải đặt một điều kiện để kiểm tra xem phần tử bạn đang tìm kiếm có trong danh sách không

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

Tất cả các chức năng được đề xuất ở đây tái tạo hành vi ngôn ngữ vốn có nhưng che khuất những gì đang diễn ra.

[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

Tại sao viết một hàm với xử lý ngoại lệ nếu ngôn ngữ cung cấp các phương thức để thực hiện những gì bạn muốn?

|
33

Nếu bạn muốn tất cả các chỉ mục, thì bạn có thể sử dụng 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),)

Đó là giải pháp rõ ràng, dễ đọc.

|
25

Tìm chỉ mục của một mục được cung cấp một danh sách có chứa nó trong Python

Đối với một danh sách ["foo", "bar", "baz"]và một mục trong danh sách "bar", cách sạch nhất để lấy chỉ mục của nó (1) trong Python là gì?

Chà, chắc chắn, có phương thức chỉ mục, trả về chỉ mục của lần xuất hiện đầu tiên:

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

Có một vài vấn đề với phương pháp này:

  • nếu giá trị không có trong danh sách, bạn sẽ nhận được ValueError
  • nếu có nhiều hơn một trong các giá trị trong danh sách, bạn chỉ nhận được chỉ mục cho giá trị đầu tiên

Không có giá trị

Nếu giá trị có thể bị thiếu, bạn cần phải bắt ValueError.

Bạn có thể làm như vậy với một định nghĩa có thể sử dụng lại như thế này:

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

Và sử dụng nó như thế này:

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

Và nhược điểm của điều này là bạn có thể sẽ kiểm tra xem giá trị được trả về ishay is notKhông:

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

Nhiều hơn một giá trị trong danh sách

Nếu bạn có thể có nhiều lần xuất hiện hơn, bạn sẽ không nhận được thông tin đầy đủ với list.index:

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

Bạn có thể liệt kê vào một danh sách hiểu các chỉ mục:

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

Nếu bạn không có lần xuất hiện nào, bạn có thể kiểm tra xem có kết quả kiểm tra boolean hay không làm gì nếu bạn lặp lại kết quả:

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

Dữ liệu tốt hơn với gấu trúc

Nếu bạn có gấu trúc, bạn có thể dễ dàng lấy thông tin này với đối tượng Sê-ri:

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

Kiểm tra so sánh sẽ trả về một loạt các booleans:

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

Chuyển chuỗi booleans đó sang chuỗi thông qua ký hiệu đăng ký và bạn chỉ nhận được các thành viên phù hợp:

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

Nếu bạn chỉ muốn các chỉ mục, thuộc tính index trả về một loạt các số nguyên:

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

Và nếu bạn muốn chúng trong một danh sách hoặc tuple, chỉ cần chuyển chúng cho hàm tạo:

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

Có, bạn cũng có thể sử dụng khả năng hiểu danh sách với liệt kê, nhưng theo tôi thì nó không thanh lịch - bạn đang thực hiện các bài kiểm tra cho sự bình đẳng trong Python, thay vì để mã dựng sẵn được viết bằng C:

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

Đây có phải là một vấn đề XY ?

Vấn đề XY là hỏi về giải pháp đã cố gắng của bạn hơn là vấn đề thực tế của bạn.

Tại sao bạn nghĩ rằng bạn cần chỉ số cho một yếu tố trong danh sách?

Nếu bạn đã biết giá trị, tại sao bạn quan tâm nó nằm ở đâu trong danh sách?

Nếu giá trị không có ở đó, thì việc nắm bắt ValueErrorkhá dài - và tôi muốn tránh điều đó.

Tôi thường lặp đi lặp lại trong danh sách dù sao đi nữa, vì vậy tôi thường giữ một con trỏ tới bất kỳ thông tin thú vị nào, lấy chỉ mục với bảng liệt kê.

Nếu bạn đang trộn dữ liệu, có lẽ bạn nên sử dụng gấu trúc - nơi có các công cụ thanh lịch hơn nhiều so với cách giải quyết Python thuần túy mà tôi đã thể hiện.

Tôi không nhớ mình cần list.index. Tuy nhiên, tôi đã xem qua thư viện chuẩn Python và tôi thấy một số cách sử dụng tuyệt vời cho nó.

Có rất nhiều, rất nhiều cách sử dụng cho nó idlelib, cho GUI và phân tích cú pháp văn bản.

Các keywordmô-đun sử dụng nó để tìm dấu hiệu bình luận trong các mô-đun để tự động tạo lại danh sách các từ khóa trong nó thông qua lập trình meta.

Trong Lib / hộp thư có vẻ như nó đang sử dụng nó như một ánh xạ được sắp xếp:

key_list[key_list.index(old)] = new

del key_list[key_list.index(key)]

Trong Lib / http / cookiejar.py, dường như được sử dụng để nhận tháng tiếp theo:

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

Trong Lib / tarfile.py tương tự như distutils để có được một lát cắt cho một mục:

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

Trong Lib / pickletools.py:

numtopop = before.index(markobject)

Điểm chung của những ứng dụng này là chúng dường như hoạt động trên danh sách các kích thước bị ràng buộc (quan trọng vì thời gian tra cứu O (n) list.index) và chúng chủ yếu được sử dụng để phân tích cú pháp (và UI trong trường hợp Idle).

Mặc dù có những trường hợp sử dụng cho nó, nhưng chúng khá hiếm. Nếu bạn thấy mình đang tìm câu trả lời này, hãy tự hỏi xem những gì bạn đang làm có phải là cách sử dụng trực tiếp nhất các công cụ được cung cấp bởi ngôn ngữ cho trường hợp sử dụng của bạn không.

|
20

Tất cả các chỉ mục với zipchức năng:

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')
|
16

Nhận tất cả các lần xuất hiện và vị trí của một hoặc nhiều mục (giống hệt nhau) trong danh sách

Với liệt kê (alist), bạn có thể lưu trữ phần tử đầu tiên (n) là chỉ mục của danh sách khi phần tử x bằng với những gì bạn tìm kiếm.

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

Hãy thực hiện chức năng của chúng tôi findindex

Hàm này lấy mục và danh sách làm đối số và trả về vị trí của mục trong danh sách, như chúng ta đã thấy trước đây.

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

Đầu ra


[1, 3, 5, 7]

Đơn giản

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

Đầu ra:

0
4
|
15

Một lựa chọn khác

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

Đơn giản là bạn có thể đi cùng

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

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

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.