Как преобразовать 2d массив в список списков в F # - PullRequest
0 голосов
/ 27 марта 2020

У меня есть 2d массив с плавающей точкой:

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

, и я хотел бы преобразовать его в список списков, где у меня есть список строк, и каждая из этих строк представляет собой список значений столбцов .

например:

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

станет:

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

Я нашел этот вопрос: F # преобразовать Array2 в список

но он конвертирует 2d массив в список, я пытаюсь найти способ конвертировать его в список списка. Я мог бы пройтись по элементам и построить список, но я уверен, что должен быть лучший способ.

Ответы [ 2 ]

2 голосов
/ 28 марта 2020

Это делается достаточно читабельным для операторов среза F # (теперь также в C# 8!). Чтобы нарезать многомерный массив, вы можете использовать .[range,range].

Например, .[*,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
]

Для ненулевых индексированных массивов, как предлагает Хенрик Хансен, предпочтительно использовать:

[ 
    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]]
1 голос
/ 29 марта 2020

Другой способ опираться на идеи Асти:

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)

Работает на разных базах.

...