F# 如何将二维数组转换为F中的列表列表#

F# 如何将二维数组转换为F中的列表列表#,f#,F#,我有一个二维浮点数数组: let scores = Array2D.init<float> width height (fun _ _ -> 0.) 将成为: [ [1, 2, 3] [4, 5, 6] [7, 8, 9] ] 我发现这个问题: 但是它将2d数组转换成一个列表,我试图找到如何将它转换成一个列表列表。 我可以遍历元素并构建列表,但我确信一定有更好的方法。这是由F的切片运算符(现在也是C 8)所提供的可读性很强的方法。 要切片多维数组,可以使用[范

我有一个二维浮点数数组:

let scores  = Array2D.init<float> width height (fun _ _ -> 0.)
将成为:

[
  [1, 2, 3]
  [4, 5, 6]
  [7, 8, 9]
]
我发现这个问题:

但是它将2d数组转换成一个列表,我试图找到如何将它转换成一个列表列表。
我可以遍历元素并构建列表,但我确信一定有更好的方法。

这是由F的切片运算符(现在也是C 8)所提供的可读性很强的方法。 要切片多维数组,可以使用
[范围,范围]

例如,
[*,n]
用于第n列,而
[n,*]
用于第n行

我们需要的最后一个部分是数组的高度,即维0,由

array.GetLength 0
现在,使用列表理解对2D数组进行切片变得很简单

[ 
    let height = arr.GetLength 0
    for row in 0..height-1  do
    yield arr.[row,*] |> List.ofArray
]
对于Henrik Hansen建议的非零索引数组,最好使用:

[ 
    for i in arr.GetLowerBound(0)..arr.GetUpperBound(0) 
        do yield arr.[i,*] |> List.ofArray 
]
测试

let counter = ref 0
//generate the test array
let arr = Array2D.init (3) (3) (fun _ _ -> Interlocked.Increment(counter))

arr |> printfn "%A"  

let lists = 
    [ 
        let height = arr.GetLength 0
        for row in 0..height - 1  do
        yield arr.[row,*] |> List.ofArray
    ]

lists |> printfn "%A"
输出:

[[1; 2; 3]
 [4; 5; 6]
 [7; 8; 9]]

[[1; 2; 3]; [4; 5; 6]; [7; 8; 9]]

另一种基于Asti想法的方法:

module Array2D =
    let toListOfLists (arr2d: 'a [,]) = [ yield! [arr2d.GetLowerBound(0)..arr2d.GetUpperBound(0)] |> List.map (fun i -> arr2d.[i,*] |> List.ofArray) ]

let base002D = Array2D.init 5 5 (fun x y -> (x, y))
let base152D = Array2D.initBased 1 5 5 5 (fun x y -> (x, y)) 

printfn "%A" (base002D |> Array2D.toListOfLists)
printfn "%A" (base152D |> Array2D.toListOfLists)

它适用于不同的基。

当第二维度的基索引不是0时,从开始到结束的切片范围
*
是否仍然有效?@kaefer它确实尊重下限。使用单个列表理解可能更简单<代码>[对于arr2d.GetLowerBound(0)…arr2d.GetUpperBound(0)中的i,不产生arr2d。[i,*]|>List.of数组]@Asti:是的,也可以。重要的是,我们必须使用上界和下界,使它能够处理除零以外的基。绝对。尽管非零索引数组相对较少,而且大多数编写的数组代码通常假定零索引。
module Array2D =
    let toListOfLists (arr2d: 'a [,]) = [ yield! [arr2d.GetLowerBound(0)..arr2d.GetUpperBound(0)] |> List.map (fun i -> arr2d.[i,*] |> List.ofArray) ]

let base002D = Array2D.init 5 5 (fun x y -> (x, y))
let base152D = Array2D.initBased 1 5 5 5 (fun x y -> (x, y)) 

printfn "%A" (base002D |> Array2D.toListOfLists)
printfn "%A" (base152D |> Array2D.toListOfLists)