2017-04-08 117 views
0

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

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其他的东西做到这一点,我的主要问题是你怎么做它,所以它只在每条线的第一个空间处分裂。

回答

1

TextIO.inputAll很好。在这种情况下,String.tokens似乎不适合这项工作。我个人只会写我自己的功能,使用String.explodeString.implodestring转换为char list或从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

下面是使用功能dropl,dropr另一个选项, splitl Substring 连同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