【问题标题】:SML : Count the number of '\n' in a StringSML:计算字符串中“\n”的数量
【发布时间】:2016-04-10 07:30:04
【问题描述】:

我是标准 ML 的新手,我有一个问题对于知道如何用这种语言编写代码的人来说可能很明显。

我有一个原始功能如下:

fun getBlocked w =
case BlockingMgr.listBlockedSuccessors w
    of nil => ""
    | ws =>
        concat (
            List.map
                (fn (r, w') => (
                    "v r1 w"
                    ^
                      Int.toString (Node.getId w))
                    ^ " w"
                    ^ (Int.toString (Node.getId (w')))
                    ^ "\n"
                )
            ws
        )       

它返回了一个完美的字符串,可以在我的程序中显示。

不幸的是,我还需要这个字符串中 '\n' 的数量。因此,我没有直接从字符串中计数(这很好),而是考虑制作另一个返回整数的函数:

fun getNbBlocked w =
    let res = 0;
    case BlockingMgr.listBlockedSuccessors w
        of nil => res
        | ws =>
            List.map
                (fn (r, w') => (
                    res = res+1
                )
            ws  

但我的大脑过于专注于程序/对象思维,我不知道如何用函数式语言执行我想要的。

如果有人可以帮我调试这个函数,因为我真的不知道问题出在哪里:/(或者更好的是,告诉我如何编写函数来计算 '\n' 的数量现有字符串)

提前感谢您的帮助!

最好的问候!

编辑

@molbdnilo 您的解决方案似乎接近解决方案,但我无法使用它:/(不幸的是,我是一个真正的初学者)。

我有这些功能(现有的和你的):

val res = 0

fun getBlocked w =
    case BlockingMgr.listBlockedSuccessors w
        of nil => ""
        | ws =>
            concat (
                List.map
                    (fn (r, w') => (
                        "v r1 w"
                        ^
                        Int.toString (Node.getId w))
                        ^ " w"
                        ^ (Int.toString (Node.getId (w')))
                        ^ "\n"
                        )
                    ws
                )       

fun count c s = List.length (List.filter (fn x => x = c) (String.explode s));;

fun count_newlines s = count #"\n" s;;

fun af w = print(getBlocked w)

fun aff w = count_newlines(getBlocked w)

当我调用函数 getBlocked() 以显示创建的字符串时

我的做法如下:

app af (Nodestore.listNodes ())

因为是调用print,所以可以在任何地方调用。

但是对于您的函数,我需要使用它的返回值,但我无法做到:/

我尝试类似:

res = (app aff Nodestore.listNodes())

(* We then, display the number of edges *)
print (Int.toString (res));

但不幸的是,并没有我想的那么简单:/

我收到错误消息:

Error: src/output/modeloutput.sml 101.11.
  Function applied to incorrect argument.
    expects: _ -> [unit]
    but got: _ -> [int]
    in: app aff
Error: src/output/modeloutput.sml 101.11.
  Function applied to incorrect argument.
    expects: [Node.node list]
    but got: [unit -> Node.node list]
    in: (app aff) Nodestore.listNodes
Error: src/output/modeloutput.sml 101.11.
  Function not of arrow type.
    function: [unit]
    in: ((app aff) Nodestore.listNodes) ()
      pre codegen raised in 2.79 + 1.50 (35% GC)
      pre codegen raised: Fail
   Compile SML raised in 2.79 + 1.50 (35% GC)
   Compile SML raised: Fail

【问题讨论】:

  • 什么是app,它有什么作用?
  • app 只是在列表的每个元素之后调用该函数 :) (但感谢您的回答,我设法使其工作:))再次感谢!

标签: algorithm functional-programming sml smlnj


【解决方案1】:

您的函数的主要问题是res = res + 1 是一个比较,而不是一个赋值。

你需要忘记分配,甚至忘记这样的事情存在。

这是做你想做的事情的一种方法:

  • 将字符串变成字符列表
  • 过滤它并只保留您感兴趣的角色
  • 取结果的长度

可能看起来像这样:

fun count c s = List.length (List.filter (fn x => x = c) (String.explode s))
fun count_newlines s = count #"\n" s

【讨论】:

  • 似乎非常接近解决方案,但我试图使用它却弄得一团糟:/(见编辑)
【解决方案2】:

我不太了解 ML,但我相信你应该使用 foldl,如下所示:

  foldl op+ 0 f

其中 op+ 是加号运算符,0 是初始值,f 是您的自定义函数,可能是匿名函数。

【讨论】:

    【解决方案3】:

    也可以直接对字符串进行递归,而无需先将它们分解为列表:

    fun countChar c "" = 0
    |   countChar c s = let val ch = String.sub (s,0) in
        (if ch = c then 1 else 0) + countChar c (String.extract (s,1,NONE))
    end;
    

    String.sub (s,0) 对应取列表头部,String.extract (s,1,NONE) 对应取尾部。我怀疑这比使用explode 更有效,因为它不需要 1 遍来建立一个列表,然后另一个来处理列表,尽管这不太可能节省大量甚至显着的时间(除非你是处理一些非常长的字符串)。

    【讨论】:

      【解决方案4】:

      我会在这里推荐 John 的解决方案,也许可以将其扩展为尾递归:

      fun countChar c s =
          let val len = String.size s
              fun cc i n = if i = len then n
                           else cc (i+1) (if String.sub (s, i) = c then n+1 else n)
          in cc 0 0
          end
      

      【讨论】:

        猜你喜欢
        • 2013-09-02
        • 2017-10-20
        • 2021-09-28
        • 1970-01-01
        • 2014-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多