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"]
enumerate
tạ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 numpy
thự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ì where
trả lại một tuple(array([2, 8], dtype=int64),)
all_id_resp_address
nên np.array
không list
.
list
và str
, rõ ràng bạn thông qua False
để np.where
. Khi bạn so sánh np.array
với smth. bạn nhận được một mảng các giá trị boolean. Sau đó np.where
tìm vị trí của tất cả các True
giá 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 numpy
giả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.timeit
vớ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_itertools
là một thư viện của bên thứ ba > pip install more_itertools
.
conda install
gầ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
:enumerate
và 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 đó .indices
for 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, n
là một bó int
s, do đó chúng tôi tìm kiếm value
, cũng được định nghĩa là một int
.while-loop
và .index
:.index
, sử dụng try-except
để xử lý lỗi vì ValueError
sẽ xảy ra nếu value
khô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_indeices
là 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]