1

如何在 Haskell 中删除字符串的第一个空格?

例如:

removeSpace " hello" = "hello"

removeSpace "  hello" = " hello"

removeSpace "hello" = "hello"
4

4 回答 4

12

这里有多个删除空间选项,以显示一些功能和做事方式。

要占用多个空格,您可以执行

removeSpaces = dropWhile (==' ')

这意味着与 相同removeSpaces xs = dropWhile (==' ') xs,但使用部分应用程序((==' ')本质上也是如此)。

或更一般的删除,

import Data.Char
removeWhitespace = dropWhile isSpace

如果您真的确定只想占用一个空格(而且您似乎确实如此),那么模式匹配是最清晰的:

removeASpace (' ':xs) = xs  -- if it starts with a space, miss that out.
removeASpace xs = xs        -- otherwise just leave the string alone

这是有效的,因为在 haskell 中,String = [Char]并且(x:xs)意味着以 list 开头x并继续的列表xs

要删除一个空格字符,我们可以使用函数保护(如果语法非常简单的 if 语句,如果你还没有遇到过的话):

removeAWhitespace "" = ""  -- base case of empty string
removeAWhitespace (x:xs) | isSpace x = xs   -- if it's whitespace, omit it
                         | otherwise = x:xs -- if it's not keep it.
于 2012-11-19T21:24:30.163 回答
6

只需使用模式匹配:

removeSpace (' ':xs) = xs
removeSpace xs = xs
于 2012-11-19T16:41:09.790 回答
4

在 Haskell 中,字符串只是字符的列表,即 Prelude 定义

type String = [Char]

此外,大约有三种方法可以编写函数:

  1. 使用您可以使用的两个最基本的工具完全自己滚动:模式匹配和递归;
  2. 巧妙结合一些已经写好的函数;而且当然
  3. 这些的混合。

如果您是 Haskell 和函数式编程的新手,我建议您使用第一种方法编写大部分函数,​​然后逐渐转向使用越来越多的预定义函数。

对于您的问题 - 删除' '字符串中的第一个空格字符 ( ) - 模式匹配和递归实际上很有意义。如前所述,字符串只是字符列表,所以我们最终只会得到一个简单的列表遍历。

让我们首先为您的函数写一个签名:

removeSpace :: [Char] -> [Char]

(我已经写[Char]了而不是String明确表示我们在这里执行列表遍历。)

与列表进行模式匹配时,我们需要考虑两种情况:列表为空 ( []) 以及由头部元素后跟尾部 ( c : cs) 组成的列表。

与往常一样,处理空列表很简单:没有剩余字符,所以没有什么要删除的,我们只需返回空列表。

removeSpace [] = []

然后是我们有一个头部元素(一个字符)和一个尾部列表的情况。这里我们需要再次区分两种情况:头部字符是空格的情况和其他任何字符的情况。

如果头部字符是空格,它将是我们遇到的第一个空格,我们需要将其删除。由于我们只需要删除第一个空格,我们可以返回列表的其余部分(即尾部)而无需进一步处理:

removeSpace (' ' : cs) = cs

剩下的就是处理头部字符不是空格的情况。然后我们需要将它保留在返回的列表中,此外,我们需要继续在列表的其余部分中寻找第一个空间;也就是说,我们需要递归地将我们的函数应用于尾部:

removeSpace (c : cs) = c : removeSpace cs

就这样。我们函数的完整定义现在为

removeSpace :: [Char]     -> [Char]
removeSpace    []         =  []
removeSpace    (' ' : cs) =  cs
removeSpace    (c   : cs) =  c : removeSpace cs

可以说,这是一个清晰简洁的定义,就像任何预定义函数的巧妙组合一样。

最后,让我们测试一下我们的函数:

> removeSpace " hello"
"hello"

> removeSpace "  hello"
" hello"

> removeSpace "hello"
"hello"

如果你真的想用预定义的函数构造你的函数,这里有一个替代定义removeSpace可以解决问题:

removeSpace :: [Char] -> [Char]    
removeSpace =  uncurry (flip (flip (++) . drop 1)) . break (== ' ')

(您可以看到为什么我更喜欢使用显式模式匹配和递归的那个。;-))

注意: 我假设您的目标确实是删除字符串中的第一个空格,无论第一个空格出现在哪里。在您给出的示例中,第一个空格始终是字符串中的第一个字符。如果总是这样,即,如果你只是在删除前导空格之后,你可以省略递归并简单地写

removeSpace :: [Char]     -> [Char]
removeSpace    []         =  []
removeSpace    (' ' : cs) =  cs
removeSpace    (c   : cs) =  c : cs

或者,结合第一个和最后一个案例,

removeSpace :: [Char]     -> [Char]
removeSpace    (' ' : cs) =  cs
removeSpace    cs         =  cs

或者,使用预定义的函数,

removeSpace :: [Char] -> [Char]
removeSpace =  uncurry ((++) . drop 1) . span (== ' ')
于 2012-11-20T10:34:59.700 回答
0

要删除字符串中任意位置的第一个空格:

removeSpace :: String -> String
removeSpace = (\(xs,ys) -> xs ++ drop 1 ys) . span (/=' ')

Wherespan抓取字符,直到找到空格或到达字符串的末尾。

然后它拆分结果并将它们放入我们获取并组合的元组中,跳过第二个列表中的第一个字符(空格)。此外,我们断言余数不是null(空列表) - 如果是,我们不能得到尾部,因为空列表不能有尾部,可以吗?所以如果是,我们只返回一个空列表。

于 2012-11-20T09:31:59.027 回答