Performance F中的返回字符串和代码优化#

Performance F中的返回字符串和代码优化#,performance,f#,f#-interactive,Performance,F#,F# Interactive,如何修改下面的代码以返回“字符串”,以便返回的输出显示在我的MVC页面上,并且希望从用户处接受enteredChar 有没有更好的方法来创建这个金字塔 当前代码: let enteredChar = 'F' // As Interactive window doesn't support to Read Input let mylist = ['A'..enteredChar] let mylistlength = mylist |> List.length let myfunc i x

如何修改下面的代码以返回“字符串”,以便返回的输出显示在我的MVC页面上,并且希望从用户处接受
enteredChar

有没有更好的方法来创建这个金字塔

当前代码:

let enteredChar = 'F' // As Interactive window doesn't support to Read Input
let mylist = ['A'..enteredChar] 
let mylistlength = mylist |> List.length
let myfunc i x tlist1 =
    (for j = 0 to mylistlength-i-2 do printf "%c" ' ')
    let a1 = [for p in tlist1  do if p < x then yield p]
    for p in a1 do printf "%c" p
    printf "%c" x
    let a2 = List.rev a1
    for p in a2 do printf "%c" p
    printfn "%s" " "

mylist |> List.iteri(fun i x -> myfunc i x mylist)

如果我理解你的问题(这可能属于),这里有一种重写函数的方法:

让showPyramid(输出:TextWriter)lastChar=
设chars=[|A'…lastChar]
设getRowChars n=
让rec循环acc i=
[|
如果i
范例

showPyramid Console.Out 'F'
或者,输出到字符串

use output = new StringWriter()
showPyramid output 'F'
let pyramid = output.ToString()
编辑
看到托马斯的答案后,我意识到我跳过了你问题中的“返回字符串”。我更新了代码并添加了一些示例来展示如何做到这一点。

作为Daniel解决方案的替代方案,您可以通过对代码逻辑进行最小的更改来实现所需的功能。您可以使用
printf.bprintf
将输出写入指定的
StringBuilder
,而不是使用将输出写入控制台的
printf.bprintf
。然后,您只需从
StringBuilder
获取结果字符串

修改后的函数如下所示。我添加了参数
str
,并将
printf
替换为
printf.bprintf str
(将
printfn
替换为
bprintf
以及其他
\n
字符):


我认为Daniel的解决方案看起来更好,但这是将打印代码转换为字符串构建代码的最直接的方法(基本上可以使用搜索和替换完成)。

一些小优化可能是:

  • 使用
    StringBuilder
    而不是
    printf
    ,这对于长字符串来说相当慢
  • 使用
    Array
    而不是
    List
    ,因为
    Array
    更适合
    String
下面是一个生成金字塔字符串的版本,它与您的代码密切相关:

open System
open System.Text

let generateString c = 
    let sb = StringBuilder()             
    let generate i x arr =
        String.replicate (Array.length arr-i-1) " " |> sb.Append |> ignore
        let a1 = Array.filter (fun p -> p < x) arr
        String(a1) |> sb.Append |> ignore
        sb.Append x |> ignore
        String(Array.rev a1) |> sb.Append |> ignore
        sb.AppendLine " " |> ignore

    let arr = [|'A'..c|]               
    arr |> Array.iteri(fun i x -> generate i x arr)
    sb.ToString()

generateString 'F' |> printfn "%s"
开放系统
开放系统.Text
设发电机限制c=
让sb=StringBuilder()
让我们生成i x arr=
String.replicate(Array.length arr-i-1)“|>sb.Append |>ignore
设a1=Array.filter(funp->psb.Append |>ignore
sb.附加x |>忽略
字符串(Array.rev a1)|>sb.Append |>ignore
sb.AppendLine“”|>忽略
设arr=[|A'..c]
arr |>Array.iteri(乐趣i x->生成i x arr)
(某人)
生成器字符串“F”|>printfn“%s”

这里有另一种方法,它似乎是功能组合的一个很好的演示。我打赌这是这里所有答案中最短的答案。:)

  • 首先,我们生成一个不寻常的初始数据数组。它的元素
    [0]
    包含一个空格或任何您想要的分隔符;出于调试目的,我更喜欢破折号(
    -
  • (1)
    行生成一个函数,用于计算要放置的字符。
    行abs(col len+1)+1
    的结果可以是正的(并且有一个要放置的字符),也可以是零负的,并且应该有一个空格。注意,没有
    if
    语句:它隐藏在
    max
    函数中
  • (2)
    行组成一个函数
    int->string
    ,用于生成一个单独的行
  • (3)
    行将上述函数作为序列初始值设定项的参数传递
这三行可以用更详细的方式书写:

    let genCell row col = row-abs(col-len+1)+1 |> max 0 |> Array.get src 
    let genRow = genCell >> Seq.init (len*2-1) >> charsToString
    Seq.init len genRow

genRow
由于函数组合的原因,不需要正式参数:参数被绑定到
genCell
,返回单个参数的函数,这正是
Seq.init
所需要的。

我想我还没有准备好函数组合。honesly仍在处理:)+1用于介绍函数组合。如果您能评论“为什么数组与字符串一起工作更好”,那将是一件好事?感谢
String(a1)
是一个构造函数,它接收一个
char
数组作为参数。此外,
Array
由于其良好的缓存位置,可能比
List
更快。
let str = StringBuilder()
mylist |> List.iteri(fun i x -> myfunc i x mylist str) 
str.ToString()
open System
open System.Text

let generateString c = 
    let sb = StringBuilder()             
    let generate i x arr =
        String.replicate (Array.length arr-i-1) " " |> sb.Append |> ignore
        let a1 = Array.filter (fun p -> p < x) arr
        String(a1) |> sb.Append |> ignore
        sb.Append x |> ignore
        String(Array.rev a1) |> sb.Append |> ignore
        sb.AppendLine " " |> ignore

    let arr = [|'A'..c|]               
    arr |> Array.iteri(fun i x -> generate i x arr)
    sb.ToString()

generateString 'F' |> printfn "%s"
let pyramid (ch:char) = 
  let ar = [| 'A'..ch |]
  let len = ar.Length
  Array.mapi
    (fun i ch -> 
      let ar = ar.[0..i]
      String.replicate (len - i - 1) " " + new string(ar) + new string((Array.rev ar).[1..]))
    ar
  |> String.concat "\n" 

pyramid 'F' |> printfn "%s"
let charsToString = Seq.map string >> String.concat String.Empty
let pyramid lastChar =
    let src = '-'::['A'..lastChar] |> List.toArray
    let len = Array.length src - 1

    fun row col -> row-abs(col-len+1)+1 |> max 0 |> Array.get src   // (1)
    >> Seq.init (len*2-1) >> charsToString                          // (2)
    |> Seq.init len                                                 // (3)

pyramid 'X' |> Seq.iter (printfn "%s")
    let genCell row col = row-abs(col-len+1)+1 |> max 0 |> Array.get src 
    let genRow = genCell >> Seq.init (len*2-1) >> charsToString
    Seq.init len genRow