You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在ML中如何让String.tokens函数输出保留分隔符?

在ML中让String.tokens输出保留分隔符的方法

String.tokens的设计逻辑就是丢弃所有匹配分隔符规则的字符,所以无法直接通过它实现保留分隔符的需求,需要自己实现一个自定义的字符串拆分函数。

原代码及问题

原代码示例:

fun f c = c = #" ";
val testStr = "int main(){return 42;}";
val stringL = String.tokens f testStr;

返回结果:

val stringL = ["int","main(){return","42;}"] : string list

期望结果:

val stringL = ["int"," ","main(){return"," ","42;}"] : string list

自定义实现方案

下面是一个能保留分隔符的拆分函数实现:

fun splitWithDelim f s =
    let
        fun aux acc current [] = 
            List.rev (if current <> "" then current :: acc else acc)
          | aux acc current (c::cs) =
            if f c then
                let
                    val newAcc = if current <> "" then str c :: current :: acc else str c :: acc
                in
                    aux newAcc "" cs
                end
            else
                aux acc (current ^ str c) cs
    in
        aux "" "" (String.explode s)
    end

(* 测试使用 *)
fun isSpace c = c = #" ";
val testStr = "int main(){return 42;}";
val stringL = splitWithDelim isSpace testStr;

这段代码运行后会返回你期望的结果:["int"," ","main(){return"," ","42;}"]。

函数逻辑说明

  1. 用String.explode把字符串转成字符列表,方便逐个遍历;
  2. 递归函数aux维护两个状态:acc是已经拆分好的结果列表(逆序存储,最后用List.rev转正),current是正在积累的非分隔符字符串;
  3. 遇到匹配分隔符规则的字符时:
    • 如果当前有积累的非分隔符字符串,就把分隔符和积累的字符串依次加入结果列表;
    • 如果没有积累的字符串(比如开头就是分隔符),只把分隔符加入结果列表;
    • 重置current为空字符串,继续遍历剩余字符;
  4. 遇到非分隔符字符时,把字符追加到current中;
  5. 遍历结束后,把最后剩余的current(如果非空)加入结果列表,再反转得到最终顺序。

关于管道操作的误区

你提到尝试用管道传递值出错,ML中的|是模式匹配的语法符号,并非其他语言里的管道操作符,所以这种方式无法实现保留分隔符的需求,需要通过自定义递归函数来处理。

内容的提问来源于stack exchange,提问作者Jace Ziegler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:04:59