【问题标题】:Concatenating strings seperated by spaces in a string list在字符串列表中连接用空格分隔的字符串
【发布时间】:2022-01-21 03:33:50
【问题描述】:

我目前正在用 SML 编写一个代码,它接收一个包含数字和空格的字符串列表。代码必须将数字组合到空格,然后为下一组数字创建一个新的列表项,依此类推。

例如,["1", "", "2", "3", "", "4", "5", "6"] 列表将返回["1", "23", "456"] 列表。

我当前的非错误尝试包括以下代码。

fun conc(L) = 
  case L of
    [] => ""
  | x::xs => x ^ conc(xs);

fun intParse(L as x::xs) = 
  let
    val intStr = conc(L)
  in    
    intStr :: intParse(xs)
  end;

我想写类似下面的代码,但不能没有错误。这不是确切的代码,更像是我无法弄清楚的伪代码。

fun strToInt(nil) = []
  | strToInt(L) = 
    let
      fun conc(y::ys) = 
        if hd(ys) <> "" then y ^ conc(ys)                           
        else y ^ ""
    in
      conc(L) :: strToInt(xs)
    end;

【问题讨论】:

    标签: recursion concatenation sml smlnj


    【解决方案1】:

    当您对列表进行递归迭代时,您需要一个基本案例。你已经想通了。我是[]

    您需要的另一件事是在迭代时可以传递的一个或多个累加器。这些累加器可以使用本地范围的辅助函数“隐藏”,您可以向该函数提供处于初始状态的累加器。

    val lst = ["1", "", "2", "3", "", "4", "5", "6"];
    
    fun lstTransform(lst) =
      let
        fun aux([], str, acc) = 
            if str = "" then List.rev(acc)
            else List.rev(str :: acc)
          | aux(x::xs, str, acc) =
            if x = "" andalso str <> "" then 
              aux(xs, "", str :: acc)
            else if x = "" then
              aux(xs, "", acc)
            else 
              aux(xs, str ^ x, acc)
      in
        aux(lst, "", [])
      end;
    

    当您遇到基本情况时,您想检查您已构建的“当前”字符串 (str) 的累加器是否为空。如果它是空的,我们只返回累加器。如果没有,我们需要将该字符串添加到累加器中。

    在任何一种情况下,由于列表的构建方式,它们会倒退,所以我们将它们反转。

    否则,您将评估列表中的第一个元素,并据此决定如何为下一次迭代更新您的状态。


    这种对列表的迭代和新值的累积正是List.foldl 的用途。这个函数让我们摆脱了很多样板。我们提供了一个作用于列表中每个元素和累加器的函数; 累加器的初始状态;以及要处理的列表。

    let 
      val (str, acc) =
        List.foldl 
          (fn (x, (str, acc)) => 
             if x = "" andalso str <> "" then ("", str :: acc)
             else if x = "" then ("", acc)
             else (str ^ x, acc))
          ("", [])
          lst
    in
      if str = "" then List.rev(acc)
      else List.rev(str :: acc)
    end;
    

    【讨论】:

      【解决方案2】:

      这是我的尝试...

      fun squoosh lst =
        let
          fun collect_and_accumulate acc collected =
            fn [] => List.rev (if collected = "" then acc else collected :: acc)
             | (""::ys) => collect_and_accumulate (if collected = "" then acc else collected :: acc) "" ys
             | (x::ys) => collect_and_accumulate acc (collected ^ x) ys; 
        in
          collect_and_accumulate [] "" lst
        end;
      

      运行下面的代码片段查看结果

      runCode();
      <pre id="code" class="lang-ml s-code-block">
      fun squoosh lst =
        let
          fun collect_and_accumulate acc collected =
            fn [] => List.rev (if collected = "" then acc else collected :: acc)
             | (""::ys) => collect_and_accumulate (if collected = "" then acc else collected :: acc) "" ys
             | (x::ys) => collect_and_accumulate acc (collected ^ x) ys; 
        in
          collect_and_accumulate [] "" lst
        end;
      
        squoosh ["1", "", "2", "3", "", "4", "5", "6"];
      </pre>
      
      
      <script src="https://unpkg.com/@sosml/interpreter@^1.5.0/build/interpreter.min.js"></script>
      <script>
        function runCode() {
          try {
            let initialState = Interpreter.getFirstState();
            const code = document.getElementById('code');
            let interpretationResult = Interpreter.interpret(code.innerText, initialState);
            console.log(interpretationResult.state.toString({ stopId: initialState.id + 1 }));
          } catch (error) {
            console.error(error.name, "\n", error.message);
          }
        }
      </script>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-13
        • 2014-07-29
        相关资源
        最近更新 更多