我想将矩阵的非零元素收集到sequence<(row,column,value)>
这不起作用
let getSparseMatrixCOO matrix =
seq {
matrix |> Array2D.iteri (fun row column elem ->
if elem <> 0.0 then yield (row, column, elem)
)
}
我是否必须放弃使用Array2D.iteri
?
答案 0 :(得分:4)
你不能在像这样的lambda函数中使用yield
。 yield
关键字只能直接在序列表达式的范围内使用(尽管您的尝试具有良好的逻辑)。
我认为最简单的选择是遍历数组的元素并编写如下内容:
let getSparseMatrixCOO matrix =
seq { for row in 0 .. Array2D.length1 matrix - 1 do
for column in 0 .. Array2D.length2 matrix - 1 do
let elem = matrix.[row, column]
if elem <> 0.0 then yield (row, column, elem) }
Array2D
模块不提供许多功能,但可以扩展为包含foldi
功能(类似于Array.foldi
)。该函数聚合数组的元素,并调用为每个元素指定的函数。然后,您可以选择所需的元素,并以您想要的方式聚合它们。
以下使用列表作为状态,并在聚合期间将非零元素附加到列表中:
Array2D.foldi (fun row column elem state ->
if elem <> 0.0 then (row, column, elem)::state else state) []
可以实现缺少的Array2D.foldi
函数(命令性地保持简单),如下所示:
module Array2D =
let foldi f a matrix =
let mutable state = a
for row in 0 .. Array2D.length1 matrix - 1 do
for column in 0 .. Array2D.length2 matrix - 1 do
state <- f row column (matrix.[row, column]) state
state
答案 1 :(得分:1)
您可以继续使用类似
的Array2D.iteri
let getSparseMatrixCOO matrix =
let result = ref List<int*int*float>.Empty
matrix |> Array2D.iteri(fun i j elem -> if elem <> 0.0 then result := (i,j,elem)::!result)
!result |> List.rev
如果您的原始意图的懒惰无关紧要,因为上面的代码段会给您相同的序列,只是热切地。