2
 for i in a..b do
     res <- res * myarray.[i]
 res

我必须像这样使用吗

  Array.fold (*) 1 (Array.sub myarray a (b - a + 1))

,我认为这相当慢而且不是那么简洁?

4

3 回答 3

5

不知道你是否会发现它更好,但你可以这样做:

Seq.fold (fun r i -> r * myarray.[i]) 1 {a .. b}
于 2012-09-19T15:59:30.387 回答
4

Daniel 的解决方案非常简洁,我认为它应该几乎与for循环一样有效,因为它不需要克隆数组。

如果您想要一个更简洁的解决方案,那么您可以使用 indexer 而不是Array.sub,它确实需要克隆数组的某些部分,但它看起来很整洁:

myarray.[a .. b] |> Seq.fold (*) 1

这会克隆数组的一部分,因为切片操作会返回一个数组。您可以定义自己的切片操作,将元素返回为seq<'T>(因此不会克隆整个数组):

module Array =
  let slice a b (arr:'T[]) = 
    seq { for i in a .. b -> arr.[i] }

使用此函数,您可以编写:

myarray |> Array.slice a b |> Seq.fold (*) 1

我相信这更直接地表达了您尝试实现的功能。与性能一样 - 您应该测量性能以查看是否需要进行此类优化,或者第一个版本是否足够快以满足您的目的。

于 2012-09-19T16:47:33.873 回答
4

如果您关心速度,那么我会回避使用 seq ,除非您正在制作原型。要么坚持使用 for 循环,要么重写为递归函数。您给出的示例很简单,有时更复杂的问题可以更好地表示为递归。

let rec rangeProduct a b total (array : _[]) =
    if a <= b then
        rangeProduct (a + 1) b (total * array.[a]) array
    else
        total

let res = myArray |> rangeProduct a b res

这里没有开销,它尽可能快,没有突变,它是功能性的。

于 2012-09-19T17:36:38.663 回答