Câu hỏi Tìm chỉ mục của một mục được đưa ra 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", làm cách nào để lấy chỉ mục (1) bằng Python?


2247
2017-10-07 01:39


gốc


Bạn có quay trở lại: [1] Chỉ số thấp nhất trong trường hợp có nhiều phiên bản "bar", [2] Tất cả các chỉ số của "bar"? - Mulliganaceous
a) Có đảm bảo rằng mục đó nằm trong danh sách, hoặc cách khác chúng ta nên xử lý trường hợp lỗi? (return None / raise ValueError) b) Các mục danh sách được bảo đảm là duy nhất, và chúng ta có nên trả lại chỉ mục đầu tiên của một trận đấu hay tất cả các chỉ mục không? - smci


Các câu trả lời:


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

Tài liệu tham khảo: Cấu trúc dữ liệu> Thêm trên danh sách

Hãy theo dõi

Lưu ý rằng mặc dù đây có lẽ là cách sạch nhất để trả lời câu hỏi như được hỏi, index là một thành phần khá yếu của list API, và tôi không thể nhớ lần cuối cùng tôi sử dụng nó trong giận dữ. Nó đã được chỉ ra cho tôi trong các ý kiến ​​rằng bởi vì câu trả lời này được tham chiếu rất nhiều, nó nên được thực hiện đầy đủ hơn. Một số lưu ý về list.index theo. Nó có lẽ là giá trị ban đầu hãy xem docstring 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 về thời gian tuyến tính trong độ dài danh sách

An index cuộc gọi kiểm tra mọi thành phần của danh sách theo thứ tự, cho đến khi nó tìm thấy kết quả phù hợp. Nếu danh sách của bạn dài và bạn không biết vị trí nào trong danh sách xuất hiện, 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. Lưu ý rằng nếu bạn biết gần đúng nơi tìm thấy kết quả phù hợp, bạn có thể cung cấp index một gợi ý. Ví dụ: trong đoạn mã này, l.index(999_999, 999_990, 1_000_000) là khoảng năm đơn vị của cường độ nhanh hơn so với thẳng l.index(999_999), bởi vì trước đây chỉ phải tìm kiếm 10 mục, trong khi 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 thứ nhất đối số của nó

Cuộc gọi đến index tìm kiếm thông qua danh sách theo thứ tự cho đến khi tìm thấy kết quả phù hợp và dừng lại ở đó. Nếu bạn mong muốn cần chỉ số của nhiều kết quả phù hợp hơn, bạn nên sử dụng biểu thức 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 những nơi mà tôi đã từng sử dụng index, Bây giờ tôi sử dụng một biểu thức hiểu danh sách hoặc trình tạo ra bởi vì chúng dễ hiểu hơn. Vì vậy, nếu bạn đang cân nhắc việc tiếp cận index, hãy xem các tính năng tuyệt vời này của python.

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

Cuộc gọi đến index kết quả trong một ValueError nế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ặt hàng có thể không có mặt trong danh sách, bạn nên

  1. Kiểm tra nó trước với item in my_list (cách tiếp cận sạch sẽ, dễ đọc), hoặc
  2. Quấn index gọi trong một try/except khối bắt ValueError (có thể nhanh hơn, ít nhất là khi danh sách tìm kiếm dài và mặt hàng thường xuất hiện).

3308
2017-10-07 01:40



được nhận thức nếu nó không có trong danh sách nó ném và lỗi! - JokerMartini
index trả về mục đầu tiên có giá trị là "bar". Nếu "bar" tồn tại hai lần trong danh sách, bạn sẽ không bao giờ tìm thấy khóa cho "thanh" thứ hai. Xem tài liệu: docs.python.org/3/tutorial/datastructures.html - mpoletto
Làm thế nào để làm điều này cho mảng numpy? - Hendy Irawan
Nó được quy định trong câu hỏi rằng mục nằm trong danh sách. - Alex Coventry
@smci, cảm ơn vì đã chỉ ra điều đó. - Alex Coventry


Một điều thực sự hữu ích trong việc 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.


786
2017-10-07 13:19





Phần lớn câu trả lời giải thích cách tìm một chỉ mục duy nhất, nhưng phương pháp của họ không trả lại 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() hàm chỉ trả về lần 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 danh sách hiểu:

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

Đây cũng là một giải pháp nhỏ với itertools.count() (đó là khá nhiều cách tiếp cận tương tự như 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 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

446
2018-06-19 22:31



Liệt kê hoạt động tốt hơn so với các phương pháp 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 'startswith' và tôi cần thu thập nhiều lần xuất hiện hoặc có cách sử dụng chỉ mục với "startswith" mà tôi không thể tìm ra - Tupelo Thistlehead
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 triển khai có thể đã thay đổi kể từ khi đo lường ở trên được đăng. - Alex Coventry
@AlexCoventry Rất phụ thuộc vào thông số kỹ thuật máy tính, nhưng gần năm năm trên (wow thời gian bay), tôi có xu hướng đồng ý với bạn. Đặc biệt từ izip đã được thực hiện dự phòng với python 3 - TerryA


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

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

123
2018-06-25 15:07





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

| mục lục(...)
   | L.index (giá trị, [bắt đầu, [dừng]]) -> số nguyên - trả về chỉ mục đầ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"])

105
2017-08-30 09:40



Và nếu không tồn tại trong danh sách? - Peter Mortensen
bạn đã thử chạy mã để xem nó trả về cái gì chưa? :-) - HongboZhu


Một vấn đề sẽ nảy 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

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



'item' là một tên biến rất sai lạc. 'index' có lẽ? - johan d.


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

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

39
2018-05-26 04:26





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 để làm những gì bạn muốn?


34
2018-05-16 16:45



Phương thức thứ 3 lặp lại hai lần trong danh sách, đúng không? - Eric Duminil
Re: "Tất cả các chức năng được đề xuất ở đây": Tại thời điểm viết có lẽ, nhưng bạn nên kiểm tra các câu trả lời mới hơn để xem câu trả lời có đúng hay không. - Peter Mortensen