index()sẽ chỉ đưa ra lần xuất hiện đầu tiên của một mục trong danh sách. Có một mẹo gọn gàng trả về tất cả các chỉ số trong một danh sách?
index()sẽ chỉ đưa ra lần xuất hiện đầu tiên của một mục trong danh sách. Có một mẹo gọn gàng trả về tất cả các chỉ số trong một danh sách?
Câu trả lời:
Bạn có thể sử dụng một danh sách hiểu:
indices = [i for i, x in enumerate(my_list) if x == "whatever"]
enumeratetại 2.3. Vì vậy, có, nếu Python của bạn là cổ xưa, sử dụng filter().
print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])trả về []thay vì [[0, 1], [0, 0], [1, 1]].
(a == 1).nonzero()đối với mảng NumPy a.
Mặc dù không phải là một giải pháp cho danh sách trực tiếp, nhưng numpythực sự tỏa sáng cho loại điều này:
import numpy as np
values = np.array([1,2,3,1,2,4,5,6,3,2,1])
searchval = 3
ii = np.where(values == searchval)[0]
trả về:
ii ==>array([2, 8])
Điều này có thể nhanh hơn đáng kể cho danh sách (mảng) với số lượng lớn các yếu tố so với một số giải pháp khác.
[0]là cần thiết 'vì wheretrả lại một tuple(array([2, 8], dtype=int64),)
all_id_resp_addressnên np.arraykhông list.
listvà str, rõ ràng bạn thông qua Falseđể np.where. Khi bạn so sánh np.arrayvới smth. bạn nhận được một mảng các giá trị boolean. Sau đó np.wheretìm vị trí của tất cả các Truegiá trị của mảng đó.
Một giải pháp sử dụng list.index:
def indices(lst, element):
result = []
offset = -1
while True:
try:
offset = lst.index(element, offset+1)
except ValueError:
return result
result.append(offset)
Nó nhanh hơn nhiều so với việc hiểu danh sách với enumerate, cho các danh sách lớn. Nó cũng chậm hơn nhiều so với numpygiải pháp nếu bạn đã có mảng, nếu không thì chi phí chuyển đổi lớn hơn tốc độ tăng (được thử nghiệm trên danh sách số nguyên với 100, 1000 và 10000 phần tử).
LƯU Ý: Lưu ý thận trọng dựa trên nhận xét của Chris_Rands: giải pháp này nhanh hơn mức hiểu danh sách nếu kết quả đủ thưa thớt, nhưng nếu danh sách có nhiều phiên bản của phần tử đang được tìm kiếm (hơn ~ 15% danh sách , trong bài kiểm tra với danh sách 1000 số nguyên), việc hiểu danh sách nhanh hơn.
timeit.timeitvới các danh sách được tạo ngẫu nhiên. Tuy nhiên, đó là một điểm quan trọng và tôi cho rằng đó có thể là lý do tại sao bạn hỏi. Vào thời điểm đó, điều đó không xảy ra với tôi, nhưng tốc độ tăng chỉ đúng nếu kết quả đủ thưa thớt. Tôi vừa thử nghiệm với một danh sách đầy đủ các yếu tố để tìm kiếm, và nó chậm hơn nhiều so với việc hiểu danh sách.
more_itertools.locate tìm các chỉ số cho tất cả các mục thỏa mãn một điều kiện.
from more_itertools import locate
list(locate([0, 1, 1, 0, 1, 0, 0]))
# [1, 2, 4]
list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b'))
# [1, 3]
more_itertoolslà một thư viện của bên thứ ba > pip install more_itertools.
conda installgần đây đã trở nên rất không ổn định trong hiệu suất)
Thêm một giải pháp (xin lỗi nếu trùng lặp) cho tất cả các lần xuất hiện:
values = [1,2,3,1,2,4,5,6,3,2,1]
map(lambda val: (val, [i for i in xrange(len(values)) if values[i] == val]), values)
Hoặc sử dụng range(python 3):
l=[i for i in range(len(lst)) if lst[i]=='something...']
Dành cho (trăn 2):
l=[i for i in xrange(len(lst)) if lst[i]=='something...']
Và sau đó (cả hai trường hợp):
print(l)
Là như mong đợi.
Sử dụng bộ lọc () trong python2.
>>> q = ['Yeehaw', 'Yeehaw', 'Googol', 'B9', 'Googol', 'NSM', 'B9', 'NSM', 'Dont Ask', 'Googol']
>>> filter(lambda i: q[i]=="Googol", range(len(q)))
[2, 4, 9]
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à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]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Đầu ra:
0
4
for-loop:enumeratevà hiểu danh sách là hiệu quả và pythonic hơn, tuy nhiên, câu trả lời này nhằm vào những sinh viên có thể không được phép sử dụng một số chức năng tích hợp sẵn đó .indicesfor i in range(len(x)):, về cơ bản lặp qua danh sách các vị trí chỉ mục[0, 1, 2, 3, ..., len(x)-1]i, nơi x[i]phù hợp với value, đểindices
def get_indices(x: list, value: int) -> list:
indices = list()
for i in range(len(x)):
if x[i] == value:
indices.append(i)
return indices
n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
print(get_indices(n, -60))
>>> [4, 8, 9]
get_indicesđược thực hiện với các gợi ý loại . Trong trường hợp này, danh sách, nlà một bó ints, do đó chúng tôi tìm kiếm value, cũng được định nghĩa là một int.while-loopvà .index:.index, sử dụng try-exceptđể xử lý lỗi vì ValueErrorsẽ xảy ra nếu valuekhông có trong danh sách.def get_indices(x: list, value: int) -> list:
indices = list()
i = 0
while True:
try:
# find an occurrence of value and update i to that index
i = x.index(value, i)
# add i to the list
indices.append(i)
# advance i by 1
i += 1
except ValueError as e:
break
return indices
print(get_indices(n, -60))
>>> [4, 8, 9]
get_indeiceslà một chút nhanh hơn (~ 15%) so với hiểu danh sách bình thường. Tôi đang cố gắng để tìm ra nó.
Nếu bạn đang sử dụng Python 2, bạn có thể đạt được chức năng tương tự với điều này:
f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))
Nơi my_listđây là danh sách mà bạn muốn để có được các chỉ số của, vàvalue là giá trị được tìm kiếm. Sử dụng:
f(some_list, some_element)
Nếu bạn cần tìm kiếm tất cả các vị trí của phần tử giữa các chỉ số nhất định , bạn có thể nêu chúng:
[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]