有一个矩阵转置功能:
let rec transpose = function
| (_::_)::_ as M -> List.map List.head M :: transpose (List.map List.tail M)
| _ -> []
[[1; 2; 3]; [4; 5; 6]; [7; 8; 9]] |> transpose |> printfn "%A"
工作正常
(_ :: _):: _ 是什么意思?
我不明白整个代码!
谁可以解释一下?
谢谢!
我找到了答案:
(_ :: _):: _ 是匹配类型整体列表列表的颜色
如果我写:
let rec transpose (M:int list list) =
match M with
| hd::tl -> List.map List.head M :: transpose (List.map List.tail M)
| _ -> []
抛出运行时异常。 hd 有问题吗?
是,当调用 List.tail 时会产生类似 [[]; []; []] 的内容,然后在调用<时抛出异常强> List.head !
问题解决了!
谢谢大家!
答案 0 :(得分:26)
该功能不是特别易读,这可能是您混淆的原因。构造(_::_)::_
是一个模式匹配的类型列表的列表,它表示当你得到非空列表的非空列表时应该运行第一个案例。
同样的事情可以这样写。这更详细,但应该清楚这里发生了什么:
let rec transpose matrix =
match matrix with // matrix is a list<list<int>>
| row::rows -> // case when the list of rows is non-empty
match row with // rows is a list<int>
| col::cols -> // case when the row is non-empty
// Take first elements from all rows of the matrix
let first = List.map List.head matrix
// Take remaining elements from all rows of the matrix
// and then transpose the resulting matrix
let rest = transpose (List.map List.tail matrix)
first :: rest
| _ -> []
| _ -> []
如您所见,我们并不真正需要值row
,rows
,col
和cols
。这就是原始实现用_
替换它们的原因(它忽略了值,只检查列表是否可以按要求的方式分解)。
在递归的情况下,我们解构矩阵如下:
[ [ x; y; y ]; [ y; y ]
[ x; y; y ]; => [ x; x; x] :: transpose [ y; y ]
[ x; y; y ] ] [ y; y ]
我希望图片让你更清楚!
答案 1 :(得分:5)
答案 2 :(得分:3)
(_::_)::_
是模式匹配。 _
只是一个未使用的变量。这相当于:
(a::b)::c as M -> List.map List.head M :: transpose (List.map List.tail M)
答案 3 :(得分:1)
这会在列表上映射head
以提取第一列,并使用它来形成转置剩余列的结果前面的第一行。
答案 4 :(得分:1)
我很抱歉碰到过时的帖子,但你原来的答案几乎是正确的。唯一错误的是空列表的终止条件。代码看起来像这样:
let rec transpose M =
match M with
| []::_ -> []
| _ -> List.map List.head M::transpose(List.map List.tail M)