Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
格式化乘法表f#输出_F#_Grid_Multiplication - Fatal编程技术网

格式化乘法表f#输出

格式化乘法表f#输出,f#,grid,multiplication,F#,Grid,Multiplication,我正在尝试使用f#创建一个nxm乘法表程序,其中N和M值由用户指定,表被计算并存储在二维数组中,并显示在控制台上 如能以类似以下格式显示我的阵列,将不胜感激: 与我的程序中的程序相反 我的源代码是 open System let func() = let multiplication n m = Array2D.init n m (fun n m -> n * m) printf "Enter N Value: " let nVa

我正在尝试使用f#创建一个nxm乘法表程序,其中N和M值由用户指定,表被计算并存储在二维数组中,并显示在控制台上

如能以类似以下格式显示我的阵列,将不胜感激:

与我的程序中的程序相反

我的源代码是

open System

let func() =
        let multiplication  n m = Array2D.init n m (fun n m -> n * m)


        printf "Enter N Value: "
        let nValue = Console.ReadLine() |> System.Int32.Parse

        printf "\nEnter M Value: "
        let mValue = Console.ReadLine() |> System.Int32.Parse

        let grid = multiplication nValue mValue 


        printfn "\n\n%A" grid

func()
我还想知道如何使我的值从1开始,而不是从0开始


我是一名F#的初学者,如果有任何帮助,我将不胜感激

你所要做的就是在n和m相乘之前加1,比如

let multiplication  n m = Array2D.init n m (fun n m -> (n + 1) * (m + 1))
然而,我们这里确实有一些括号疯狂,您可以如下重构它:

let myMultFunction n m = (n + 1) * (m + 1)
let multiplication n m = Array2D.init n m myMultFunction
格式化会有点棘手,使用for循环有点欺骗,而且不是很F#,但是考虑到我们使用的是2d数组,它们在本质上不起作用,我想我可以通过;)


格式化输出,就像任何UI任务一样,通常会变得异常棘手。这种情况也不例外

我们的想法是:

  • 计算出表格的“单元格”应该有多宽
  • 通过将转换为字符串并填充到单元格宽度的数字连接在一起来构建每一行
  • 在第一行前面加上前缀
  • 用换行符连接所有分隔行
  • 首先,让我们看看如何计算“单元格”的宽度。表中最宽的数字是多少?假设
    n
    m
    都是正数,那么最宽的数字显然是
    n*m
    。我们可以这样计算单元格的宽度:

    let cellWidth = (n*m) |> string |> String.length
    
    类似地,第一列(最左边)的宽度与其中最大的数字相同,即
    n

    let firstColWidth = n |> string |> String.length
    
    现在,让我们自己做一个函数,它将接受一个数字,并用空格填充到所需的宽度:

    let pad totalWidth (value: obj) = 
        let s = string value
        if s.Length >= totalWidth then s
        else (String.replicate (totalWidth-s.Length) " ") + s
    
    这个函数很容易理解:如果字符串已经超过最大值,只需返回它,否则在它前面加上
    (totalWidth-s.Length)
    空格

    使用此函数,我们可以格式化网格中的一行:

    let formatRow rowIdx =
        let cells = [for colIdx in 0..m-1 -> grid.[rowIdx,colIdx] |> pad cellWidth] // Each cell in this row padded to `cellWidth`
        let firstCol = (rowIdx+1) |> pad firstColWidth  // Leftmost column - just the row index itself padded to `firstColWidth`
        let wholeRow = firstCol :: cells  // Whole row consists of the leftmost column plus subsequent cells
        String.concat " " wholeRow
    
    同样,设置最上面一行的格式:

    let firstRow = 
        let cols = [for col in 1..m -> col |> pad cellWidth]
        let firstCol = " " |> pad firstColWidth
        let wholeRow = firstCol :: cols
        String.concat " " wholeRow
    
    看看这些函数有多相似:唯一的区别是
    网格。[rowIdx,colIdx]
    col
    。我们为什么不概括一下呢

    let formatRowWith firstCell getCell =
        let cells = [for colIdx in 0..m-1 -> getCell colIdx |> pad cellWidth]
        let firstCol = firstCell |> pad firstColWidth
        let wholeRow = firstCol :: cells
        String.concat " " wholeRow
    
    let formatRow rowIdx = formatRowWith (rowIdx+1) (fun c -> grid.[rowIdx,c])
    let firstRow = formatRowWith " " (fun c -> c+1)
    
    最后,格式化每一行,在第一行前面加上前缀,并将它们连接在一起:

    let rows = [0..n-1] |> List.map formatRow
    let allRows = firstRow :: rows
    String.concat "\n" allRows
    
    最终代码:

    let formatGrid (grid:_[,]) =
        let n, m = grid.GetLength 0, grid.GetLength 1
        let cellWidth = (n*m) |> string |> String.length
        let firstColWidth = n |> string |> String.length
    
        let pad totalWidth (value: obj) = 
            let s = string value
            if s.Length >= totalWidth then s
            else (String.replicate (totalWidth-s.Length) " ") + s
    
        let formatRowWith firstCell getCell =
            let cells = [for colIdx in 0..m-1 -> getCell colIdx |> pad cellWidth]
            let firstCol = firstCell |> pad firstColWidth
            let wholeRow = firstCol :: cells
            String.concat " " wholeRow
    
        let formatRow rowIdx = formatRowWith (rowIdx+1) (fun c -> grid.[rowIdx,c])
        let firstRow = formatRowWith " " id
    
        let rows = [0..n-1] |> List.map formatRow
        let allRows = firstRow :: rows
        String.concat "\n" allRows
    

    我厚颜无耻地复制了Fyodor Soikin优秀答案的某些部分,但修改了其余部分,使代码更“实用”和更短,尽管对那些有“命令式”倾向的人来说不太清楚

    输出为:

    val it : string = "
       123
    1| 123
    2| 456
    "
    

    谢谢,这很有效:)关于如何设置表格格式有什么建议吗?列表理解功能非常完善,没有任何必要。在许多有抱负的程序员中,存在着将“功能性”与“难以理解”混为一谈的倾向。不要成为它的牺牲品。@FyodorSoikin-这就是为什么我在引用标记中加上“功能性”的原因。
    let pad totalWidth (value: obj) = 
        let s = string value
        if s.Length >= totalWidth then s
        else (String.replicate (totalWidth - s.Length) " ") + s
    
    let formatGrid (grid:_[,]) =
        let n, m = grid.GetLength 0, grid.GetLength 1
        let cellWidth = (n*m) |> string |> String.length
        let firstColWidth = n |> string |> String.length
    
        let frow str (rw: int []) = (Array.fold (fun s i -> s + (pad cellWidth i)) str rw) + "\n"
        let firstRow = frow ("\n" + pad (firstColWidth+2) "") [|1..m|]
        let folder str i = str + (frow ((pad firstColWidth (i+1)) + "| ") grid.[i, 0..])
    
        List.fold folder firstRow [0..(n-1)]
    
    let a2d = array2D [[1;2;3]; [4;5;6]]
    formatGrid a2d
    
    val it : string = "
       123
    1| 123
    2| 456
    "