index()просто дасть перше виникнення елемента в списку. Чи є акуратний трюк, який повертає всі показники у списку?
index()просто дасть перше виникнення елемента в списку. Чи є акуратний трюк, який повертає всі показники у списку?
Відповіді:
Ви можете використати розуміння списку:
indices = [i for i, x in enumerate(my_list) if x == "whatever"]
enumerateу 2.3. Так що так, якщо ваш Python стародавній, використовуйте filter().
print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])повертається []замість [[0, 1], [0, 0], [1, 1]].
(a == 1).nonzero()для масиву NumPy a.
Хоча це не рішення для списків безпосередньо, він numpyсправді світить для таких речей:
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]
повертає:
ii ==>array([2, 8])
Це може бути значно швидше для списків (масивів) з великою кількістю елементів порівняно з деякими іншими рішеннями.
[0]потрібна, тому що whereповертається кортеж(array([2, 8], dtype=int64),)
all_id_resp_addressповинно бути np.arrayНЕ list.
listі str, очевидно , ви пройшли Falseв np.where. Якщо порівнювати np.arrayз smth. ви отримуєте масив булевих значень. Потім np.whereзнаходить позиції всіх Trueзначень цього масиву.
Рішення з використанням 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)
enumerateДля великих списків це набагато швидше, ніж розуміння списку. Це також набагато повільніше, ніж numpyрішення, якщо у вас вже є масив, інакше вартість перетворення перевищує швидкість посилення (тестується у цілих списках зі 100, 1000 та 10000 елементами).
ПРИМІТКА . Зауваження про застереження на основі коментаря Chris_Rands: це рішення швидше, ніж розуміння списку, якщо результати досить рідкі, але якщо в списку є багато примірників шуканого елемента (більше ~ 15% списку , на тесті зі списком 1000 цілих чисел), розуміння списку відбувається швидше.
timeit.timeitвипадкові списки. Це важливий момент, і, мабуть, саме тому ви питаєте. У той час мені це не прийшло в голову, але підвищення швидкості справджується лише в тому випадку, якщо результати є досить рідкими. Я щойно перевірив список, повний елемента для пошуку, і це набагато повільніше, ніж розуміння списку.
more_itertools.locate знаходить показники для всіх предметів, які задовольняють умові.
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є сторонньою бібліотекою > pip install more_itertools.
conda installостаннім часом виявився дуже нестабільним у виконанні)
Ще одне рішення (вибачте, якщо дублікати) для всіх випадків:
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)
Або Використовуйте range(python 3):
l=[i for i in range(len(lst)) if lst[i]=='something...']
Для (python 2):
l=[i for i in xrange(len(lst)) if lst[i]=='something...']
І тоді (обидва випадки):
print(l)
Як очікувалося.
Використання filter () у 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]
Ви можете створити вирок за замовчуванням
from collections import defaultdict
d1 = defaultdict(int) # defaults to 0 values for keys
unq = set(lst1) # lst1 = [1, 2, 2, 3, 4, 1, 2, 7]
for each in unq:
d1[each] = lst1.count(each)
else:
print(d1)
За допомогою перерахування (alist) ви можете зберігати перший елемент (n), що є індексом списку, коли елемент x дорівнює тому, що ви шукаєте.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Ця функція приймає елемент і список як аргументи і повертає позицію елемента в списку, як ми бачили раніше.
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"))
Вихідні дані
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Вихід:
0
4
for-loop:enumerateта розуміння списку є більш ефективними та пітонічними, однак ця відповідь спрямована на студентів, яким може бути заборонено використовувати деякі з цих вбудованих функцій .indicesfor i in range(len(x)):якого, по суті, повторюється список списків індексів[0, 1, 2, 3, ..., len(x)-1]i, де x[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реалізовані підказками типу . У цьому випадку список, nє купою ints, тому ми шукаємо value, також визначений як int.while-loopта .index:.index, використовуйте try-exceptдля обробки помилок, оскільки ValueErrorвиникне, якщо valueйого немає в списку.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трохи швидше (~ 15%), ніж звичайне розуміння списку. Я намагаюся це зрозуміти.
Якщо ви використовуєте Python 2, ви можете досягти такої ж функціональності з цим:
f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))
Де my_listзнаходиться список, у якому ви хочете отримати індекси, і valueяке значення шукається. Використання:
f(some_list, some_element)
Якщо вам потрібно знайти позиції всіх елементів між певними індексами , ви можете вказати їх:
[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]