SML splitting string on first space

僤鯓⒐⒋嵵緔 提交于 2019-12-12 02:34:54

问题


As of right now I am reading in an entire input file using inputAll and then using String.tokens to split each word at every occurrence of space.

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

Ex) "red blue green" would look like this

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

However, now I would like to change it to only split the string at the first occurrence of a space char on each line.

Ex) "red blue green" should look like

["red", "blue green"]

I have a feeling I will need to utilize something other than inputAll to accomplish this, and my main question is how do you make it so it only splits at the first space of each line.


回答1:


TextIO.inputAll is fine. In this case it seems that String.tokens is not the right tool for the job. Personally I would just write my own function, using String.explode and String.implode to convert a 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

In context, you could use this as follows.

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

For example, if your input file was this:

red blue green
yellow orange purple pink

then lines' would look like this:

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



回答2:


Here is another option using the functions dropl, dropr, and splitl of Substring along with 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


来源:https://stackoverflow.com/questions/43289155/sml-splitting-string-on-first-space

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!