Tìm chỉ mục của một mục trong danh sách


3181

Đưa ra một danh sách ["foo", "bar", "baz"]và một mục trong danh sách "bar", làm thế nào để tôi có được chỉ mục của nó ( 1) trong Python?


6
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"?
Ṃųỻịgǻňạc thiết ơ

4
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?
smci

Xem các câu trả lời với tích hợp numpy, mảng numpy hiệu quả hơn nhiều so với danh sách Python. Nếu danh sách ngắn thì không có vấn đề gì khi tạo một bản sao của nó từ danh sách Python, nếu không thì có lẽ bạn nên xem xét việc lưu trữ các phần tử trong mảng numpy ở vị trí đầu tiên.
Athanassios

Câu trả lời:


4484
>>> ["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 nên xem tài liệu về nó:

list.index(x[, start[, end]])

Trả về chỉ mục dựa trên zero trong danh sách của mục đầu tiên có giá trị bằng x . Tăng một ValueErrornếu không có mặt hàng đó.

Các đối số tùy chọn bắt đầukết thúc được diễn giải như trong ký hiệu lát cắt và được sử dụng để giới hạn tìm kiếm ở một phần tiếp theo cụ thể của danh sách. Chỉ mục được trả về được tính tương đối so với phần đầu của chuỗi đầy đủ hơn là đối số bắt đầu.

Độ 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ì trước đây chỉ phải tìm kiếm 10 mục, trong khi đoạn 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ó chỉ số khớp nhiều 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 khái quát 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 Python.

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

20
chỉ mục trả về mục đầu tiên có giá trị là "bar". Nếu "thanh" 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

2
Nếu bạn chỉ tìm kiếm một yếu tố (đầu tiên), tôi thấy rằng index()nó chỉ nhanh hơn 90% so với việc hiểu danh sách so với danh sách các số nguyên.
slybloty

Cấu trúc dữ liệu nào nên được sử dụng nếu danh sách rất dài?
izhang05

@izhang: Một số chỉ mục phụ, như {phần tử -> list_index} dict, nếu các phần tử có thể băm và vị trí trong danh sách có vấn đề.
Alex Coventry

898

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.


2
bpython là một cách thân thiện với người dùng để đọc tài liệu theo kiểu tương tác.
goetzc

@davidavr có, nhưng sau đó những người còn lại chỉ muốn google nó thay vì cuộn qua các tài liệu trợ giúp sẽ không có bộ tùy chọn xếp hạng đẹp, trung tâm này. :)
honkaboy

556

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

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

3
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.
Alex Coventry

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


132

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

2
Và nếu không tồn tại trong danh sách?
Peter Mortensen

1
Mục không tồn tại sẽ tăng ValueError
Nam G VU

1
Câu trả lời này sẽ phù hợp hơn ở đây: stackoverflow.com/questions/6294179/
Khăn

86

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


58

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

1
Điều này giúp chúng tôi tránh thử bắt!
devssh

Tuy nhiên, nó có thể tăng gấp đôi độ phức tạp. Có ai kiểm tra không?
stefanct

@stefanct Độ phức tạp thời gian vẫn là tuyến tính nhưng nó sẽ lặp qua danh sách hai lần.
Tiếp

@ApproachingDarknessFish Đó rõ ràng là điều tôi muốn nói. Ngay cả khi về mặt giáo dục, đó là cùng một thứ tự phức tạp, lặp đi lặp lại hai lần có thể là một bất lợi nghiêm trọng trong nhiều trường hợp sử dụng do đó tôi đã đưa nó lên. Và chúng ta vẫn chưa biết câu trả lời ...
stefanct

44

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?


9
Phương pháp thứ 3 lặp lại hai lần trong danh sách, phải 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 liệu nó có còn đúng không.
Peter Mortensen

41

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.


4
Thế còn danh sách các chuỗi, danh sách các đối tượng không phải là số, v.v ...?
Laryx Decidua

1
Câu trả lời này nên được đăng tốt hơn tại đây: stackoverflow.com/questions/6294179/
Kẻ

1
Đây là một trong những tốt nhất tôi đã đọc. mảng numpy hiệu quả hơn nhiều so với danh sách Python. Nếu danh sách ngắn thì không có vấn đề gì khi tạo một bản sao của nó từ danh sách Python, nếu không thì có lẽ nhà phát triển nên xem xét việc lưu trữ các phần tử trong mảng numpy ở vị trí đầu tiên.
Athanassios

35

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 điều đó bằng kiểm tra kết quả boolean hoặc 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 ValueErrorsẽ khá dài dòng - 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ác cách giải quyết Python thuần túy mà tôi đã thể hiện.

Bản thân tôi không nhớ 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ông dụng cho nó trong idlelib , cho GUI và phân tích cú pháp văn bản.

Các keyword sử dụng mô-đun 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 để có được 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ều mà những cách sử dụng này dường như có điểm chung là dường như chúng 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) cho 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.



21

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

1
Câu trả lời này nên được đăng tốt hơn tại đây: stackoverflow.com/questions/6294179/ cấp
Cristik

16

Đơ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]

16

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

1
Câu trả lời này nên được đăng tốt hơn tại đây: stackoverflow.com/questions/6294179/
Kẻ

15

Và bây giờ cho một cái gì đó hoàn toàn khác nhau...

... Giống như xác nhận sự tồn tại của vật phẩm trước khi lấy chỉ mục. Điều hay ho của cách tiếp cận này là hàm luôn trả về một danh sách các chỉ mục - ngay cả khi đó là một danh sách trống. Nó hoạt động với các chuỗi là tốt.

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

Khi dán vào cửa sổ python tương tác:

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

Cập nhật

Sau một năm phát triển trăn đầu xuống, tôi hơi bối rối với câu trả lời ban đầu của mình, vì vậy để thiết lập hồ sơ thẳng, người ta chắc chắn có thể sử dụng mã trên; tuy nhiên, nhiều cách thành ngữ hơn để có được những hành vi tương tự sẽ sử dụng danh sách hiểu biết, cùng với enumerate function ().

Một cái gì đó như thế này:

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

Mà, khi dán vào một cửa sổ python tương tác mang lại:

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

Và bây giờ, sau khi xem xét câu hỏi này và tất cả các câu trả lời, tôi nhận ra rằng đây chính xác là những gì FMc gợi ý trong câu trả lời trước đó của mình . Vào thời điểm ban đầu tôi trả lời câu hỏi này, tôi thậm chí không nhìn thấy câu trả lời đó, vì tôi không hiểu nó. Tôi hy vọng rằng ví dụ có phần dài dòng hơn của tôi sẽ giúp hiểu.

Nếu một dòng mã ở trên vẫn không có ý nghĩa với bạn, tôi thực sự khuyên bạn nên 'hiểu danh sách python' của Google và dành vài phút để tự làm quen. Đây chỉ là một trong nhiều tính năng mạnh mẽ giúp sử dụng Python để phát triển mã.


12

Một biến thể của câu trả lời từ FMc và user7177 sẽ đưa ra một lệnh có thể trả về tất cả các chỉ số cho bất kỳ mục nào:

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

Bạn cũng có thể sử dụng điều này như một lớp lót để có được tất cả các chỉ số cho một mục nhập. Không có gì đảm bảo cho hiệu quả, mặc dù tôi đã sử dụng bộ (a) để giảm số lần gọi lambda.


1
Câu trả lời này nên được đăng tốt hơn tại đây: stackoverflow.com/questions/6294179/ cấp
Cristik

10

Giải pháp này không mạnh mẽ như các giải pháp khác, nhưng nếu bạn là người mới bắt đầu và chỉ biết về forcác vòng lặp thì vẫn có thể tìm thấy chỉ mục đầu tiên của một mặt hàng trong khi tránh ValueError:

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

9

Tìm chỉ mục của mục x trong danh sách L:

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

4
Điều này lặp lại mảng hai lần, do đó nó có thể dẫn đến các vấn đề về hiệu năng cho các mảng lớn.
Cristik

Đồng ý. Nếu danh sách dài đáng kể, tôi sẽ tìm thứ khác. Không nên là một vấn đề lớn cho các danh sách vừa và nhỏ.
Ketan

5

Vì danh sách Python dựa trên zero, nên chúng tôi có thể sử dụng hàm tích hợp zip như sau:

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

trong đó "haystack" là danh sách được đề cập và "kim" là mục cần tìm.

(Lưu ý: Ở đây chúng tôi đang lặp lại bằng cách sử dụng i để lấy các chỉ mục, nhưng nếu chúng ta cần tập trung vào các mục, chúng ta có thể chuyển sang j.)


3
[i cho tôi, j trong liệt kê (haystack) nếu j == 'kim'] nhỏ gọn hơn và dễ đọc hơn, tôi nghĩ vậy.
Giovanni G. PY

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

Tài khoản này cho nếu chuỗi cũng không có trong danh sách, nếu nó không có trong danh sách thì location = -1


4

index()Phương thức Python đưa ra lỗi nếu không tìm thấy mục. Vì vậy, thay vào đó, bạn có thể làm cho nó tương tự như indexOf()chức năng của JavaScript sẽ trả về -1nếu không tìm thấy mục này:

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

5
tuy nhiên, JavaScript có triết lý rằng các kết quả kỳ lạ tốt hơn các lỗi, do đó, rất hợp lý khi trả về -1, nhưng trong Python, nó có thể khó theo dõi lỗi, vì -1 trả về một mục từ cuối danh sách.
Sapphire_Brick

3

Có một câu trả lời chức năng hơn cho điều này.

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

Hình thức chung hơn:

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

1
Câu trả lời này cảm thấy như ở nhà cho những người đam mê Scala/ lập trình chức năng
y2k-shubham

3

Hãy đặt tên lstcho danh sách mà bạn có. Người ta có thể chuyển đổi danh sách lstthành a numpy array. Và, sau đó sử dụng numpy.where để lấy chỉ mục của mục đã chọn trong danh sách. Sau đây là cách mà bạn sẽ thực hiện nó.

import numpy as np

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

>>> 1

2

Đối với những người đến từ một ngôn ngữ khác như tôi, có thể với một vòng lặp đơn giản, việc hiểu và sử dụng nó dễ dàng hơn:

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

Tôi biết ơn vì vậy chính xác thì liệt kê làm gì? . Điều đó giúp tôi hiểu.


2

Nếu bạn định tìm một chỉ mục một lần thì sử dụng phương pháp "index" là ổn. Tuy nhiên, nếu bạn định tìm kiếm dữ liệu của mình nhiều lần thì tôi khuyên bạn nên sử dụng mô-đun bisect . Hãy nhớ rằng sử dụng dữ liệu mô-đun bisect phải được sắp xếp. Vì vậy, bạn sắp xếp dữ liệu một lần và sau đó bạn có thể sử dụng bisect. Sử dụng mô-đun bisect trên máy của tôi nhanh hơn khoảng 20 lần so với sử dụng phương pháp chỉ mục.

Dưới đây là một ví dụ về mã sử dụng cú pháp Python 3.8 trở lên:

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

Đầu ra:

t1=0.0400, t2=0.0020, diffs t1/t2=19.60

1

Nếu hiệu suất là mối quan tâm:

Nó được đề cập trong nhiều câu trả lời rằng phương thức tích hợp của list.index(item)phương thức là thuật toán O (n). Sẽ ổn nếu bạn cần thực hiện điều này một lần. Nhưng nếu bạn cần truy cập vào các chỉ số của các phần tử một số lần, thì trước tiên bạn nên tạo một từ điển (O (n)) của các cặp chỉ mục vật phẩm, sau đó truy cập vào chỉ mục tại O (1) mỗi khi bạn cần nó

Nếu bạn chắc chắn rằng các mục trong danh sách của bạn không bao giờ lặp lại, bạn có thể dễ dàng:

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.

Nếu bạn có thể có các phần tử trùng lặp và cần trả về tất cả các chỉ mục của chúng:

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

Như được chỉ định bởi @TerryA, nhiều câu trả lời thảo luận về cách tìm một chỉ mục.

more_itertoolslà một thư viện của bên thứ ba với các công cụ để định vị nhiều chỉ mục trong một lần lặp.

Được

import more_itertools as mit


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

Tìm chỉ số của nhiều quan sát:

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

Kiểm tra nhiều mục:

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

Xem thêm tùy chọn với more_itertools.locate. Cài đặt qua > pip install more_itertools.


0

sử dụng từ điển, trong đó xử lý danh sách trước và sau đó thêm chỉ mục vào đó

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]

-1

theo ý kiến ​​của tôi ["foo", "bar", "baz"].index("bar")là tốt nhưng nó không đủ! bởi vì nếu "thanh" không có trong từ điển, được ValueErrornêu ra. Vì vậy , bạn có thể sử dụng chức năng này:

def find_index(arr, name):
    try:
        return arr.index(name)
    except ValueError:
        return -1

if __name__ == '__main__':
    print(find_index(["foo", "bar", "baz"], "bar"))

và kết quả là:

1

và nếu tên không có trong mảng, hàm trả về -1. Ví dụ:

in (find_index (["foo", "thanh", "baz"], "fooo"))

-1


1
Đừng sử dụng điều này bởi vì l = [1, 2]; find_index(l, 3)sẽ trở lại -1l[find_index(l, 3)]sẽ trở lại 2. -1 là một điều xấu để trở lại, chỉ cần trả lại Không có.
Daniel Stracaboško

-1 là hợp đồng bạn có thể trả lại bất cứ điều gì bạn muốn Nhưng hãy thử sử dụng ít hơn Không có trong các chương trình của bạn bởi vì Không hoặc Null trong giao tiếp chương trình của bạn với các chương trình khác như các trang web Android và PHP có thể khiến chương trình bị hỏng, ví dụ bạn có thể trả về null trong JSON và ứng dụng điện thoại trang web của bạn sẽ đóng hoặc trả về Lỗi 500 (lỗi máy chủ nội bộ).
NaabNuts
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.