【发布时间】:2015-04-26 04:13:58
【问题描述】:
我刚刚遇到一个案例,在 Array2D 上使用 fold/foldi 方法会很有用,我想知道,如果有原因,为什么 Array2D 没有它们。
由于我的 array2d 非常庞大,我不想先将其转换为其他格式。
这仅仅是一个罕见的用例还是有技术原因,为什么没有添加这些方法?或者有没有办法在不接触数组中的数据的情况下实现同样的效果(如移动它)?
【问题讨论】:
标签: f#
我刚刚遇到一个案例,在 Array2D 上使用 fold/foldi 方法会很有用,我想知道,如果有原因,为什么 Array2D 没有它们。
由于我的 array2d 非常庞大,我不想先将其转换为其他格式。
这仅仅是一个罕见的用例还是有技术原因,为什么没有添加这些方法?或者有没有办法在不接触数组中的数据的情况下实现同样的效果(如移动它)?
【问题讨论】:
标签: f#
我认为在标准Array2D 模块中拥有这个功能会非常有用。您可以为the Visual F# repository 开一个问题并帮助我们添加它:-)。
除了@scrwtp 写的,你还可以使用更直接的可变实现。对于像这样的基本功能,我认为使用突变很好,而且会更快一些:
let foldi (folder: int -> int -> 'S -> 'T -> 'S) (state: 'S) (array: 'T[,]) =
let mutable state = state
for x in 0 .. Array2D.length1 array - 1 do
for y in 0 .. Array2D.length2 array - 1 do
state <- folder x y state (array.[x, y])
state
【讨论】:
我不认为Array2D 没有在标准中提供这些功能有什么特别的原因,因为它确实有map/mapi。无论如何,使用锯齿状数组可能会更好地处理您想要处理多维数组的用例,因此几乎没有添加它们的动机。
你没有理由不能自己定义它们。
这是一个折叠的例子:
let foldi (folder: int -> int -> 'S -> 'T -> 'S) (state: 'S) (array: 'T[,]) =
seq {
for x in 0 .. Array2D.length1 array - 1 do
for y in 0 .. Array2D.length2 array - 1 do
yield (x, y, array.[x, y])
}
|> Seq.fold (fun acc (x, y, e) -> folder x y acc e) state
如需常规折叠和更深入的解释,请查看here。
【讨论】:
如果我需要使用折叠函数,我通常使用 Seq.cast,但这仅适用于 fold(不适用于 foldi)。
我正在添加这个解决方案,如果需要,例如,扫描:
let array2dFold folder (state:'State) (source:'T[,]) =
source
|> ( Seq.cast<'T> >> Seq.fold folder state )
由于它不依赖于变异,它很可能比以前的解决方案慢。
【讨论】: