如何在 Haskell 中删除字符串的第一个空格?
例如:
removeSpace " hello" = "hello"
removeSpace " hello" = " hello"
removeSpace "hello" = "hello"
如何在 Haskell 中删除字符串的第一个空格?
例如:
removeSpace " hello" = "hello"
removeSpace " hello" = " hello"
removeSpace "hello" = "hello"
这里有多个删除空间选项,以显示一些功能和做事方式。
要占用多个空格,您可以执行
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.
只需使用模式匹配:
removeSpace (' ':xs) = xs
removeSpace xs = xs
在 Haskell 中,字符串只是字符的列表,即 Prelude 定义
type String = [Char]
此外,大约有三种方法可以编写函数:
如果您是 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 (== ' ')
要删除字符串中任意位置的第一个空格:
removeSpace :: String -> String
removeSpace = (\(xs,ys) -> xs ++ drop 1 ys) . span (/=' ')
Wherespan
抓取字符,直到找到空格或到达字符串的末尾。
然后它拆分结果并将它们放入我们获取并组合的元组中,跳过第二个列表中的第一个字符(空格)。此外,我们断言余数不是null
(空列表) - 如果是,我们不能得到尾部,因为空列表不能有尾部,可以吗?所以如果是,我们只返回一个空列表。