SML在第一个空格

时间:2017-04-08 01:12:54

标签: sml smlnj

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

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

前)“红蓝绿”看起来像这样

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

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

例)“红蓝绿”应该看起来像

["red", "blue green"]

我有一种感觉,我需要利用inputAll之外的其他东西才能实现这一目标,而我的主要问题是如何制作它以便它只在每行的第一个空格处分割。

2 个答案:

答案 0 :(得分:1)

TextIO.inputAll没问题。在这种情况下,似乎String.tokens不适合这项工作。就个人而言,我只想编写自己的函数,使用String.explodeString.implodestring转换为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")]

答案 1 :(得分:1)

这是使用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