Вот простая рекурсивная функция, которая делает то же самое:
let rec subStringIndices (haystack:string) (needle:string) (from:int) =
let index = haystack.IndexOf(needle, from)
if index >= 0 then
let rest = subStringIndices haystack needle (index + 1)
index::rest
else []
printfn "%A" (subStringIndices "abaabababaaab" "ab" 0)
Функция принимает дополнительный параметр from
, который представляет начальный индекс (с которого вы хотите начать поиск в строке).Первоначально, это установлено в ноль.В функции мы сначала получаем следующий индекс.Если мы что-то найдем, мы рекурсивно обработаем оставшуюся часть строки (начиная с index + 1
) и вернем список, содержащий индекс и все рекурсивно полученные индексы.
Несколько более элегантная и более эффективная версия, использующая хвостовая рекурсия может быть записана с использованием параметра аккумулятора трюк и вложенная функция:
let subStringIndices (haystack:string) (needle:string) =
let rec loop (from:int) acc =
let index = haystack.IndexOf(needle, from)
if index >= 0 then
loop (index + 1) (index::acc)
else
List.rev acc
loop 0 []
Рекурсивное зацикливание теперь реализовано функцией loop
.Он получает haystack
и needle
как параметры извне, поэтому их не нужно копировать в стек.Мы накапливаем индексы в списке acc
, переданном в качестве параметра, и когда мы достигаем конца, мы возвращаем список (в обратном порядке, потому что мы добавляли новые элементы в начало списка).