Первое и последнее вхождение без метода count и циклов
Дана строка. Если в этой строке буква f встречается только один раз, выведите её индекс. Если она встречается два и более раз, выведите индекс её первого и последнего появления. Если буква f в данной строке не встречается, ничего не выводите. При решении этой задачи нельзя использовать метод count и циклы. это решение которое проходит проверку:
s = input() a = s.find('f') b = s.rfind('f') if a == -1: print() elif a == b: print(a) else: print(a, b)
есть ли решения это задачи которые бы соответствовали требованиям
При решении этой задачи нельзя использовать метод count и циклы.
Отслеживать
52.3k 11 11 золотых знаков 108 108 серебряных знаков 312 312 бронзовых знаков
задан 3 фев 2018 в 6:47
35 1 1 золотой знак 1 1 серебряный знак 5 5 бронзовых знаков
7 ответов 7
Сортировка: Сброс на вариант по умолчанию
str.index
Чтобы распознать случаи: 0, 1, 2+ вхождений без явных циклов, s.count(‘f’) метода, очевидная альтернатива s.find() методу из вопроса — это s.index() :
#!/usr/bin/env python3 s = input() count = len(s) - len(s.replace('f', '')) if count == 0: pass elif count == 1: print(s.index('f')) else: # count > 1 print(s.index('f'), s.rindex('f'))
try/except
Можно без явного if :
try: i = s.index('f') except ValueError: # count == 0 pass else: try: j = s.rindex('f', i+1) except ValueError: # count == 1 print(i) else: # count > 1 print(i, j)
Рекурсия
Можно рекурсивный find() реализовать:
def find(char, s, i=0): return -1 if i == len(s) else i if char == s[i] else find(char, s, i+1)
Тогда решение почти идентично варианту из вопроса (разница в том, что ничего не выводится для count==0 случая) :
s = input() i = find('f', s) j = len(s) - 1 - find('f', s[::-1]) # rfind('f', s) if i == -1: # count == 0 pass elif i == j: # count == 1 print(i) else: # count > 1 print(i, j)
Итераторы
Можно find() даже без индексации и явного len(s) реализовать:
def find(char, s, i=0): it = iter(s) first = next(it, None) return -1 if first is None else i if first == char else find(char, it, i+1)
Распаковка аргументов
Можно вообще не вызывать явно встроенные функции, опираясь на распаковку аргументов:
def find(char, s): def f(first, *rest, i=0): return i if first == char else -1 if not rest else f(*rest, i=i+1) return -1 if not s else f(*s)
Связные списки
Используя это представление, можно со строками как со связными списками работать. К примеру, чтобы обратить строку, получив связный список:
def reversed_as_llist(s): def f(first, *rest, llist=None): return f(*rest, llist=(first, llist)) if rest else (first, llist) return f(*s) if s else None
>>> reversed_as_llist('abc') ('c', ('b', ('a', None)))
Используя явные функции доступа:
first = lambda llist: llist[0] if llist else None rest = lambda llist: llist[1] if llist else None
легко найти размер списка, реализовать поиск по аналогии с приведёнными решениями:
def llist_len(llist, size=0): return llist_len(rest(llist), size+1) if llist else size def llist_find(char, llist, i=0): return -1 if not llist else i if char == first(llist) else llist_find(char, rest(llist), i+1)
Это позволяет определить rfind() без len(s) и индексации ( s[::-1] ):
def rfind(char, s): L = reversed_as_llist(s) i = llist_find(char, L) return i if i == -1 else llist_len(L) - 1 - i
При желании, можно отказаться и от рекурсии с именованными функциями (к примеру, используя Y combinator) и даже не использовать явно числа (к примеру, заменяя на Church numerals).
heapq.nlargest
Если использовать встроенные функции, стандартную библиотеку, то есть множество решений, которые скрывают явный цикл и позволяют без .count(‘f’) обойтись:
import heapq indices = heapq.nlargest(2, range(len(s)), key=lambda i: s[i] == 'f') fs = ''.join(map(s.__getitem__, indices)) if fs == 'ff': # count == 2+ print(*indices) elif fs[:1] == 'f': # count == 1 print(indices[0]) # else print nothing # count == 0
Вывести индексы всех вхождений элемента в списке
Создайте функцию, которая вернет индексы всех вхождений элемента в списке.
Примеры:
get_indices(["a", "a", "b", "a", "b", "a"], "a") ➞ [0, 1, 3, 5]get_indices([1, 5, 5, 2, 7], 7) ➞ [4]get_indices([1, 5, 5, 2, 7], 5) ➞ [1, 2]get_indices([1, 5, 5, 2, 7], 8) ➞ []
Примечание:
- Если элемента нет в списке, то возвращаем [] .
- Индекс списка начинается с 0.
- Без вложенных списков и сложных конструкций внутри списка.
Решение:
def get_indices(lst, el): return [i for i in range(len(lst)) if lst[i] == el]
def get_indices(lst, el): list = [] for i in range(len(lst)): if lst[i] == el: list.append(i) return list
Python: проверить индекс элемента в списке
Списки полезны по-разному по сравнению с другими типами данных из-за их универсальности. В этой статье мы рассмотрим одну из самых распространенных операций со списками — поиск индекса элемента.
Мы рассмотрим различные сценарии поиска элемента, то есть нахождение первого, последнего и всех вхождений элемента. А также что происходит, когда искомого элемента не существует.
Использование Функции index()
Все операции, упомянутые в предыдущем абзаце, можно выполнить с помощью встроенной функции index() . Синтаксис этой функции:
index(element[, start[, end]])
Параметр element , естественно, представляет собой элемент который мы ищем. Параметры start и end являются необязательными и представляют диапазон индексов, в котором мы ищем element .
Значение по умолчанию для start — 0 (поиск с начала), а значение по умолчанию для end — это количество элементов в списке (поиск до конца списка).
Функция возвращает первую позицию element в списке, которую она могла найти, независимо от того, сколько равных элементов осталось после первого вхождения.
Нахождение первого появления элемента
Использование функции index() без установки каких-либо значений для start и end даст нам первое вхождение искомого element :
my_list = ['a', 'b', 'c', 'd', 'e', '1', '2', '3', 'b'] first_occurrence = my_list.index('b') print("First occurrence of 'b' in the list: ", first_occurrence)
Что даст нам ожидаемый результат:
First occurrence of 'b' in the list: 1
Поиск всех вхождений элемента
Чтобы найти все вхождения элемента, мы можем использовать необязательный параметр start , чтобы мы выполняли поиск только в определенных сегментах списка.
Например, предположим, что первое вхождение элемента в index 3 . Чтобы найти следующий, нам нужно будет продолжить поиск первого появления этого элемента после индекса 3 . Мы будем повторять этот процесс, меняя место начала поиска, пока мы найдем новые вхождения элемента:
my_list = ['b', 'a', 2, 'n', False, 'a', 'n', 'a'] all_occurrences = [] last_found_index = -1 element_found = True while element_found: try: last_found_index = my_list.index('a', last_found_index + 1) all_occurrences.append(last_found_index) except ValueError: element_found = False if len(all_occurrences) == 0: print("The element wasn't found in the list") else: print("The element was found at: " + str(all_occurrences))
Запуск этого кода даст нам:
The element was found at: [1, 5, 7]
Здесь нам пришлось использовать блок try , так как функция index() выдает ошибку, когда не может найти указанный element в заданном диапазоне. Это может быть необычно для разработчиков, которые больше привыкли к другим языкам, поскольку такие функции обычно возвращают -1 / null , когда элемент не может быть найден.
Однако в Python мы должны быть осторожны и использовать блок try при использовании этой функции.
Другой, более изящный способ сделать то же самое — использовать понимание списка и полностью игнорировать функцию index() :
my_list = ['b', 'a', 2, 'n', False, 'a', 'n', 'a'] all_occurrences = [index for index, element in enumerate(my_list) if element == 'a'] print("The element was found at: " + str(all_occurrences))
Что даст нам тот же результат, что и раньше. У этого подхода есть дополнительное преимущество в том, что он не использует блок try .
Нахождение последнего появления элемента
Если вам нужно найти последнее вхождение элемента в списке, есть два подхода, которые вы можете использовать с функцией index() :
- Переверните список и найдите первое вхождение в перевернутом списке
- Просмотрите все вхождения элемента и отслеживайте только последнее вхождение
Что касается первого подхода, если бы мы знали первое вхождение element в обратном списке, мы могли бы найти позицию последнего вхождения в исходном. В частности, мы можем сделать это, вычтя reversed_list_index — 1 из длины исходного списка:
my_list = ['b', 'a', 2, 'n', False, 'a', 'n', 'a'] reversed_list_index = my_list[::-1].index('n') # or alteratively: # reversed_list_index2 = list(reversed(my_list)).index('n') original_list_index = len(my_list) - 1 - reversed_list_index print(original_list_index)
Что даст нам желаемый результат:
Что касается второго подхода, мы могли бы настроить код, который мы использовали, чтобы найти все вхождения, и отслеживать только последнее обнаруженное вхождение:
my_list = ['b', 'a', 2, 'n', False, 'a', 'n', 'a'] last_occurrence = -1 element_found = True while element_found: try: last_occurrence = my_list.index('n', last_occurrence + 1) except ValueError: element_found = False if last_occurrence == -1: print("The element wasn't found in the list") else: print("The last occurrence of the element is at: ", last_occurrence)
Что даст нам тот же результат:
Вывод
Мы рассмотрели некоторые из наиболее распространенных способов использования функции index() и способы избежать ошибки в некоторых случаях.
Помните о потенциально необычном поведении функции index() , когда она выдает ошибку вместо возврата -1 / None , когда элемент не найден в списке.
Как найти индекс значения в массиве NumPy (с примерами)
Вы можете использовать следующие методы, чтобы найти положение индекса определенных значений в массиве NumPy:
Метод 1: найти все ценные позиции в индексе
np.where (x== value )
Метод 2: найти первую позицию индекса значения
np.where (x== value )[0][0]
Метод 3: найти первую позицию индекса нескольких значений
#define values of interest vals = np.array([ value1 , value2 , value3 ]) #find index location of first occurrence of each value of interest sorter = np.argsort (x) sorter[np.searchsorted (x, vals, sorter=sorter)]
В следующих примерах показано, как использовать каждый метод на практике.
Метод 1: найти все ценные позиции в индексе
В следующем коде показано, как найти каждую позицию индекса, которая равна определенному значению в массиве NumPy:
import numpy as np #define array of values x = np.array([4, 7, 7, 7, 8, 8, 8]) #find all index positions where x is equal to 8 np.where (x== 8 ) (array([4, 5, 6]),)
Из вывода мы видим, что позиции индекса 4, 5 и 6 равны значению 8 .
Метод 2: найти первую позицию индекса значения
В следующем коде показано, как найти первую позицию индекса, равную определенному значению в массиве NumPy:
import numpy as np #define array of values x = np.array([4, 7, 7, 7, 8, 8, 8]) #find first index position where x is equal to 8 np.where (x== 8 )[0][0] 4
Из вывода мы видим, что значение 8 сначала встречается в позиции индекса 4.
Метод 3: найти первую позицию индекса нескольких значений
В следующем коде показано, как найти первую позицию индекса нескольких значений в массиве NumPy:
import numpy as np #define array of values x = np.array([4, 7, 7, 7, 8, 8, 8]) #define values of interest vals = np.array([4, 7, 8]) #find index location of first occurrence of each value of interest sorter = np.argsort (x) sorter[np.searchsorted (x, vals, sorter=sorter)] array([0, 1, 4])
Из вывода мы видим:
- Значение 4 сначала встречается в индексной позиции 0.
- Значение 7 сначала встречается в индексной позиции 1.
- Значение 8 сначала встречается в индексной позиции 4.
Дополнительные ресурсы
В следующих руководствах объясняется, как выполнять другие распространенные операции в NumPy: