在Haskell中开始使用字符串

时间:2011-02-18 17:29:29

标签: haskell

我需要编写一个带有gggggggeeeeetttttt字符串的函数,并且可以计算字母重复和输出的次数为g7e5t6。

我刚刚开始使用Haskell,所以不确定从哪里开始。

4 个答案:

答案 0 :(得分:13)

函数group将列表中的相同元素组合在一起。由于字符串是一个字符列表,我们有:

group "ggggeeetttt" = ["gggg","eee","tttt"]

要收到这封信,我们可以使用map head,因为head接受字符串(或任何列表)的第一个元素:

map head ["gggg","eee","tttt"] = ['g','e','t']

现在,我们想知道每个子字符串中有多少个元素。这可以使用map length

完成
map length ["gggg","eee","tttt"] = [4,3,4]

让我们将这些数字转回字符串:

map show [4,3,4] = ["4","3","4"]

现在我们需要以某种方式组合原始列表和长度列表。我们可以这样做:

zipWith (:) ['g','e','t'] ["4","3","4"]

zipWith会将指定的函数应用于两个列表中的配对元素。在这里,我使用了(:),它在列表的开头添加了一个元素。

这为您提供了完成所需操作所需的所有构建块。例如,这应该有效,尽管我还没有测试过:

f s = concat $ zipWith (:) letters lengths
    where
        groups  = group s
        letters = map head groups
        lengths = map (show . length) groups

答案 1 :(得分:7)

变异与理解,有点漂亮(考虑以前的解释只是代码):

ghci> let s = "gggggggeeeeetttttt"
ghci> putStrLn $ concat [head g: show (length g) | g <- group s]
g7e5t6

答案 2 :(得分:3)

最好的开始方式是弄清楚你的问题。我建议采用以下方法:

  1. 将字符串拆分为相等字符的子字符串。因此,您需要一个函数,它接受String并返回一个字符串列表([String])。
    示例:splitStr "gggggggeeeeetttttt"应返回["ggggggg","eeeee","tttttt"]
    令人高兴的是,模块Data.List已经提供了这样一个函数,它名为group
  2. 计算重复次数和重复的字母。重复次数只是子列表的长度,请使用length
  3. 获取重复的角色并将其粘贴在重复次数之前。对于重复的字符,我们可以使用任何一个列表,我们采取第一个。要计算列表的第一个元素(也称为字符串),可以使用head。例如。 head "abc"会产生'a' 要将它固定在长度的前面,你可以使用一个小的辅助函数和show,它将大多数东西变成一个字符串。我们的助手看起来像这样:makeRepetitions string = head string : show (length string): aka cons在列表的前面添加了一个元素。
  4. 将步骤(3)的帮助器应用于(1)中字符串列表的所有元素。我们使用mapmap将函数应用于值列表并返回结果列表
  5. 将子列表汇总到您的结果中。我们可以使用concat。实际上,我们可以使用concatMap来组合(4)和(5)。此函数将函数映射到值列表并将结果连接起来 - 就像我们想要的那样。
  6. 现在,您的代码如下所示:

    import Data.List
    
    runlength :: String -> String
    runlength string = concatMap makeRepetitions (group string)) where
      makeRepetitions string = head string : show (length string)
    

    因为很多括号很烦人,Haskellers经常使用.。点结合了两个函数来创建一个新函数。您可以认为f = functionA . functionB等于f x = functionA (functionB x)。使用点,我们可以重新格式化程序:

    import Data.List
    
    runlength :: String -> String
    runlength = concatMap makeRepetitions . group where
      makeRepetitions string = head string : show (length string)
    

    IMO,这种表示更具可读性。您可以将runlength视为管道。首先应用group,然后我们使用concatMapmakeRepetitions映射到输入上并连接结果。

答案 3 :(得分:1)

滥用箭头和无点:)

f = group >>> concatMap (head &&& (show . length) >>> uncurry (:))

这是适用的:

f = concatMap ((:) <$> head <*> (show . length)) . group