SML 在第一个 space 上拆分字符串

SML splitting string on first space

截至目前,我正在使用 inputAll 读取整个输入文件,然后在每次出现 space 时使用 String.tokens 拆分每个单词。

val file = TextIO.openIn input
val _input = TextIO.inputAll file
val _ = TextIO.closeIn file
String.tokens Char.isSpace _input

Ex) "red blue green" 看起来像这样

["red", "blue", "green"]

但是,现在我想将其更改为仅在每行第一次出现 space 字符时拆分字符串。

Ex) "red blue green" 应该看起来像

["red", "blue green"]

我觉得我需要利用 inputAll 以外的东西来完成这个,我的主要问题是你如何做到这一点,所以它只在每行的第一个 space 处拆分。

TextIO.inputAll 没问题。在这种情况下,String.tokens 似乎不是完成这项工作的正确工具。就我个人而言,我只会编写自己的函数,使用 String.explodeString.implode 来转换 string to/from char list.

fun splitCharsFirstSpace cs =
  case cs of
    [] => ([], [])
  | c :: cs' =>
      if Char.isSpace c then ([], cs')
      else let val (l, r) = splitCharsFirstSpace cs'
           in (c :: l, r)
           end

fun splitFirstSpace s =
  let
    val (l, r) = splitCharsFirstSpace (String.explode s)
  in
    (String.implode l, String.implode r)
  end

在上下文中,您可以按如下方式使用它。

val file = TextIO.openIn input
val contents = TextIO.inputAll file
val _ = TextIO.closeIn file
val lines = String.tokens (fn c => c = #"\n") contents
val lines' = List.map splitFirstSpace lines

例如,如果您的输入文件是这样的:

red blue green
yellow orange purple pink

那么 lines' 将如下所示:

[("red", "blue green"), ("yellow", "orange purple pink")]

这是另一个使用 Substring 的函数 dropl、dropr 和 splitl 的选项 连同 TextIO.inputLine.

  structure SS = Substring;
  structure C = Char;
  structure TIO = TextIO;

  fun splitFile(arg) =
  let val file = TIO.openIn arg
      val line = TIO.inputLine file;
      fun trimWs ss = (SS.dropl (C.isSpace) (SS.dropr (C.isSpace) ss));
      fun splitLine(SOME str) acc =
        let val (l, r) = SS.splitl (not o C.isSpace) (SS.full str);
            val (l, r) = (trimWs l, trimWs r);
         in if SS.size l + SS.size r = 0
               then splitLine (TIO.inputLine file) acc
               else (SS.string l, SS.string r)::splitLine (TIO.inputLine file) acc
        end
        | splitLine (NONE) acc = acc;
      val result = splitLine line [];
      val _ = TextIO.closeIn file
   in result end