帮我解释一下F#Matrix转置功能

时间:2010-06-10 16:00:09

标签: f#

有一个矩阵转置功能:

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 !


问题解决了!
谢谢大家!

5 个答案:

答案 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
    | _ -> []
  | _ -> [] 

如您所见,我们并不真正需要值rowrowscolcols。这就是原始实现用_替换它们的原因(它忽略了值,只检查列表是否可以按要求的方式分解)。

在递归的情况下,我们解构矩阵如下:

[ [ x; y; y ];                               [ y; y ] 
  [ x; y; y ];   =>  [ x; x; x] :: transpose [ y; y ]
  [ x; y; y ] ]                              [ y; y ] 

我希望图片让你更清楚!

答案 1 :(得分:5)

这也可能对您有所帮助:

Understanding a Matrix transposition Function in Haskell

在类似的编程语言(Haskell)中它是一个非常相似的函数。

答案 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)