如何在haskell中的空格后拆分字符串?

Cla*_*orm 0 string recursion haskell

我知道 Haskell 没有循环,所以我不能那样做。我也知道递归在这里是“有用的”,但这就是我所知道的。到目前为止,我已经获得了一个基本的类型签名,即

toSplit :: String -> [String]
Run Code Online (Sandbox Code Playgroud)

基本上,它从一个字符串变成了一个单词列表......

谢谢!

PS我想使用takeWhiledropWhile功能......不是图书馆......

Ste*_*fan 5

如果你想自己实现它,你需要做的第一件事就是找到第一个词。你可以这样做:

takeWhile (/=' ') s
Run Code Online (Sandbox Code Playgroud)

如果字符串以分隔符开头,则需要先修剪这些字符。我们可以用dropWhile.

takeWhile (/=' ') $ dropWhile (==' ') s
Run Code Online (Sandbox Code Playgroud)

现在我们有了第一个单词,但我们还需要从第一个单词开始的字符串的其余部分,我们将在其上递归。我们可以使用splitAt

(_, rest) = splitAt (length word) s
Run Code Online (Sandbox Code Playgroud)

然后我们rest对字符串的 进行递归,并将第一个单词 cons 到该递归的结果上,从而为我们提供所有单词的列表。

我们需要定义基本情况,即空字符串的结果,一旦没有更多字符,它将终止递归。

toSplit :: String -> [String]
toSplit "" = []
toSplit s =
  let word = takeWhile (/=' ') $ dropWhile (==' ') s
      (_, rest) = splitAt (length word) s
  in word : toSplit (dropWhile (==' ') rest)
Run Code Online (Sandbox Code Playgroud)

编辑:上面的代码中有一个错误,它没有正确处理边缘情况。

错误在于它在原始文件上调用 splitAt ,s但如果s有前导空格,则会产生错误的结果:

*Main> toSplit " foo"
["foo","o"]
Run Code Online (Sandbox Code Playgroud)

这应该修复错误:

let trimmed = dropWhile (==' ') s
    word = takeWhile (/=' ') trimmed
    (_, rest) = splitAt (length word) trimmed
Run Code Online (Sandbox Code Playgroud)

这留下了一个边缘情况:

*Main> toSplit " "
[""]
Run Code Online (Sandbox Code Playgroud)

一种可能的解决方案是使用辅助函数:

toSplit :: String -> [String]
toSplit = splitWords . dropWhile (==' ') 
    where
        splitWords "" = []
        splitWords s = 
          let word = takeWhile (/=' ') s
              (_, rest) = splitAt (length word) s
          in word : splitWords (dropWhile (==' ') rest)
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用 `span` 而不是 `takeWhile` 和 `splitAt` (2认同)