Часть, которая делает ваше функциональное решение уродливым, пропускает i-й элемент, что означает индексы. Вытяните это в многократно используемую функцию, чтобы вся уродливая обработка индекса была изолирована. Я называю мой RoundRobin.
let RoundRobin l = seq {
for i in {0..Seq.length l - 1} do
yield (Seq.nth i l, Seq.take i l |> Seq.append <| Seq.skip (i+1) l)
}
Хотя, если вы хотите создать эффективную версию, это может быть намного уродливее.
Я не смог найти product
в модуле Seq, поэтому я написал свой собственный.
let prod (l : seq<float>) = Seq.reduce (*) l
Теперь создать код довольно просто:
let Lagrange pos value desiredPos = Seq.sum (seq {
for (v,(p,rest)) in Seq.zip value (RoundRobin pos) do
yield v * prod (seq { for p' in rest do yield (desiredPos - p') / (p - p') })
})
RoundRobin гарантирует, что pos [i] не включен с остальной частью pos во внутреннем цикле. Чтобы включить массив val
, я заархивировал его с круглым массивом pos
.
Урок здесь заключается в том, что индексирование очень уродливо в функциональном стиле.
Также я обнаружил интересный трюк: |> Seq.append <|
дает вам синтаксис инфикса для добавления последовательностей. Не так хорошо, как ^
.