首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >打印桌子

打印桌子
EN

Code Review用户
提问于 2016-09-26 14:22:04
回答 2查看 134关注 0票数 3

我有一个递归函数,它打印了一个表,但是我真的认为我目前的解决方案很难看。有人知道我如何改进我的解决方案吗?

我试图在没有任何变量的情况下使用sprintf来实现。

代码语言:javascript
运行
AI代码解释
复制
let rec rec n =
   if n > 0 then
      rec(n-1) + sprintf "\n"+sprintf "%d" (n*1) + sprintf "\t%d" (n*1)+ sprintf "\t%d" (n*2) + sprintf "\t%d" (n*3) + sprintf "\t%d" (n*4)
+ sprintf "\t%d" (n*5) + sprintf "\t%d" (n*6) + sprintf "\t%d" (n*7) + sprintf "\t%d" (n*8) + sprintf "\t%d" (n*9) + sprintf "\t%d" (n*10)
   else
      sprintf "\t%d" 1 + sprintf "\t%d" 2 + sprintf "\t%d" 3 + sprintf "\t%d" 4 + sprintf "\t%d" 5 + sprintf "\t%d" 6 + sprintf "\t%d" 7 + sprintf "\t%d" 8 + sprintf "\t%d" 9 + sprintf "\t%d" 10
printfn "%s" (rec 6)
EN

回答 2

Code Review用户

发布于 2016-09-26 19:15:32

首先,sprintf不只是采取一个论点,这将不是很有用的。它所使用的参数(以及相应类型)与格式字符串中提到的一样多。

所以,不是这样的:

代码语言:javascript
运行
AI代码解释
复制
   sprintf "%d" (n*1) + sprintf "\t%d" (n*2)

你可以这样做:

代码语言:javascript
运行
AI代码解释
复制
   sprintf "%d\t%d" (n*1) (n*2)

其次,所有这些sprintf调用看起来都与我非常相似。当有重复的时候,通常会有一种方法通过参数化来缩短它。您的sprintfs的第一行可能是这样的:

代码语言:javascript
运行
AI代码解释
复制
   let columns = [1..10] |> List.map ( (*) n ) |> String.concat "\t"
   sprintf "\n%s" columns

你的第二行sprintfs根本不需要任何sprintfs

代码语言:javascript
运行
AI代码解释
复制
   "\t1\t2\t3\t4\t5\t6\t7\t8\t9\t10"

(尽管您也可以使用一个列表来表示清楚,特别是如果您希望使它对不同数量的列有用)

第三,这个递归函数永远不会完成。仔细看一看:从来没有这个函数不调用自己的情况。当n=0的时候,它会用n=6来称呼自己,当n>0时,它会用n=n-1来称呼自己。所以,一旦你称之为它,它就会无限期地自我标榜。嗯,不完全是无限期的,但是直到它用完为止。

根据您的解释(“打印一个表”),我得出的结论是,您真正想要的是首先打印标题(常量字符串),然后在它下面打印6行,每行10个数字。对吗?如果是这样的话,基本大小写应该只返回标头,每个非基本大小写都应该构造它的行并将先前的结果加到它的前面:

代码语言:javascript
运行
AI代码解释
复制
let row n = 
   [1..10]
   |> List.map ( (*) n ) 
   |> String.concat "\t"
   |> sprintf "\n%s"

let rec table n =
   if n > 0 then table (n-1) + row n
   else "\t1\t2\t3\t4\t5\t6\t7\t8\t9\t10"

第四,这一任务并不真正需要递归。是的,您可以将任何顺序进程编码为递归函数,但递归很难实现。要正确理解(如本例所示)是很棘手的,在阅读代码时更难理解。解决此类问题的通常方法是将递归(在核心库中)编码一次,作为参数化函数(对于线性过程,这类函数通常称为fold),然后在更高级别的代码中使用该函数或其导数。在您的特殊情况下,由于您只想生成几个字符串并将它们连接起来,所以我将使用map

代码语言:javascript
运行
AI代码解释
复制
let row n = 
   [1..10]
   |> List.map ( (*) n ) 
   |> String.concat "\t"
   |> sprintf "\n%s"

let table n = 
   let header = "\t1\t2\t3\t4\t5\t6\t7\t8\t9\t10"
   let rows = [1..n] |> List.map row
   sprintf "%s\n%s" header (String.concat "\n" rows)
票数 6
EN

Code Review用户

发布于 2016-09-27 07:40:12

递归解决方案可以是:

代码语言:javascript
运行
AI代码解释
复制
let print rows cols = 
  let listRow row =  ([1 .. cols] |> List.fold (fun str n -> sprintf "%s\t%d" str (n * row)) "")
  let head = listRow 1

  let rec doRow row = 
    if row <= rows then
      let curline = sprintf "%d%s" row  (listRow row)
      let nextlines = doRow (row + 1)
      sprintf "%s\n%s" curline nextlines
    else
      ""
  sprintf "%s\n%s" head (doRow 1)

[<EntryPoint>]
let main argv = 
  printfn "%s" (print 6 10)

  Console.ReadLine()|>ignore
  0

以及一个基于清单的版本:

代码语言:javascript
运行
AI代码解释
复制
let print rows cols = 
  let listRow row = 
    [1 .. cols] 
    |> List.map (fun n -> sprintf "%d" (n * row)) 
    |> String.concat "\t"

  let header = sprintf "\t%s" (listRow 1)

  let table = 
    [1 .. rows]
    |> List.map (fun n -> sprintf "%d\t%s" n (listRow n))
    |> String.concat "\n"

  sprintf "%s\n%s" header table
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/142542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文