Если вам нужно оглянуться назад на произвольное количество элементов, то использование Array.fold
напрямую может быть не лучшим вариантом, так как функция предназначена для сценариев, в которых вы можете обрабатывать элементы один за другим.
Нет ничего плохого в использовании прямого доступа к массивам в F # - если вы не изменяете их, вы все еще пишете функциональный код (поэтому, возможно, рекурсия + прямой доступ с использованием индексов будет работать в вашем сценарии).
Как указывает Инь Чжу, вы можете сгенерировать массив частей массива (используя Seq.windowed
), но создание O (n) количества маленьких массивов может быть довольно затратным. Вот более сложный прием, который вы также можете использовать:
Я вижу, что вам нужно вызывать функцию aCalc
только с соответствующей частью массива в качестве аргумента. Вы можете создать простую оболочку для массива, которая обеспечивает доступ только к соответствующей части массива, например:
type ArraySlice<'a>(arr:'a[], from, max) =
member x.Item
with get(index) =
let index = index + from
if index > max || index < from then failwith "out of range"
arr.[index]
Насколько я понимаю ваш код, вам нужно сгенерировать количество просмотров элементов на основе результата, поэтому вам, вероятно, нужно будет написать это, используя один fold
, что можно сделать примерно так:
// If you write this using lambdas or local 'let' binding, the
// 'dataArray' value will be in scope, so you don't need to keep it as
// part of the state...
(dataArray, (0, initResult)) ||> Array.fold (fun (i, result) item ->
let n = numItemsToLookBack (result, item)
let recent = new ArraySlice<_>(dataArray, max 0 (i - n), i - 1)
// Note: modify aCalc, so that it takes 'ArraySlice'
let result = aCalc(result, item, recent)
i + 1, result)