代码之家  ›  专栏  ›  技术社区  ›  kev

帮我解释F#矩阵转置函数

f#
  •  14
  • kev  · 技术社区  · 14 年前

    有一个 功能:

    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)
        | _ -> []
    

    它引发运行时异常。有什么问题吗 高清
    是的 ,它让人觉得 列表.tail ,则调用时抛出异常 列表.head



    谢谢大家!

    5 回复  |  直到 14 年前
        1
  •  28
  •   Nathan Shively-Sanders    13 年前

    这个函数写得不太好,这可能是您感到困惑的原因。构造 (_::_)::_ 是类型的值的模式匹配 INT列表

    同样的事情也可以这样写。这是更详细的,但应该很清楚这里发生了什么:

    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 ] 
    

    我希望这张照片能让你看得更清楚!

        2
  •  5
  •   Community CDub    7 年前
        3
  •  3
  •   Turtle    14 年前

    (_::_)::_ 是模式匹配。 _

    (a::b)::c as M -> List.map List.head M :: transpose (List.map List.tail M)
    
        4
  •  3
  •   zorrooo    8 年前

    很抱歉我碰到了一个过时的帖子,但你原来的答案几乎是对的。唯一错误的是空列表的终止条件。代码应该如下所示:

    let rec transpose M = 
        match M with 
        | []::_ -> []
        | _ -> List.map List.head M::transpose(List.map List.tail M)
    
        5
  •  1
  •   J D    14 年前

    这个地图 head