使用Haskell删除字符串中的第一个空格

时间:2012-11-19 16:39:26

标签: haskell

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

例如:

removeSpace " hello" = "hello"

removeSpace "  hello" = " hello"

removeSpace "hello" = "hello"

4 个答案:

答案 0 :(得分: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)表示以x开头并继续列出xs的列表。

要删除一个空格字符,我们可以使用函数保护(如果语法很轻,如果你没有遇到它们的语句):

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.

答案 1 :(得分:6)

只需使用模式匹配:

removeSpace (' ':xs) = xs
removeSpace xs = xs

答案 2 :(得分:3)

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

type String = [Char]

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

  1. 使用您可以使用的两个最基本的工具完全自己滚动:模式匹配和递归;
  2. 巧妙地结合一些已编写的功能;当然,
  3. 这些的混合。
  4. 如果您不熟悉Haskell和函数编程,我建议您使用第一种方法编写大部分函数,​​然后逐渐转向使用越来越多的预定义函数。

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

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

    removeSpace :: [Char] -> [Char]
    

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

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

    处理空列表一如既往地简单:没有剩下的字符,所以没有任何东西可以删除,我们只返回空列表。

    removeSpace [] = []
    

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

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

    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 (== ' ')
    

答案 3 :(得分:0)

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

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

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

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