【问题标题】:Shortening a String Haskell缩短字符串 Haskell
【发布时间】:2011-03-04 06:49:54
【问题描述】:

如何在 Haskell 中用给定的数字缩短字符串。

说:

comp :: String -> String
short :: String -> String

chomp (x:xs) = (x : takeWhile (==x) xs)

使用comp 我想从字符串的开头选择一系列重复的字符,使用 最多包含九个字符的运行。

例如:

short "aaaavvvdd" 将输出"aaaa"short "dddddddddd" 输出"ddddddddd"

我知道我需要take,但不确定如何将其放入代码中。

我已经做到了,但它不起作用

short x:xs | length(short x:xs) >9 = take(9)
           | otherwise = comp

【问题讨论】:

  • 这是作业吗?如果是,请添加作业标签。
  • 不,我只是觉得无聊,决定自学haskell
  • 到目前为止,您的定义非常好,您只是在语法上苦苦挣扎。这就是我认为你试图写的内容:short xs | length (chomp xs) > 9 = take 9 xs | otherwise = chomp xs。不是世界上最有效的东西,但它会让你开始。

标签: haskell


【解决方案1】:

快速回答

import Data.List
short [] = []
short x = (take 9 . head . group) x  

这将为您提供与您想要的输出相匹配的输出。

也就是说,

*> short "aaaavvvdd"
"aaaa"
*> short "dddddddddd"
"ddddddddd"

逐步开发

使用“组”来分隔项目

此解决方案依赖于 Data.List 库中的“组”功能。我们从定义开始:

short x = group x

这给了我们:

*> short "aaaavvvddd"
["aaaa","vvv","ddd"]

使用“head”只返回第一个元素

一旦我们拥有列表中的元素,我们只需要列表的第一项。我们使用“head”来实现这一点:

short x = (head . group) x

“。”是函数组合的 Haskell 函数。同理:

short x = head (group x)

short x = head $ group x

这会给我们:

*> short "aaaavvvdd"
"aaaa"
*> short "dddddddddddddd"
"dddddddddddddd"

使用“take”获取前九个字符

我们只取这个结果的前九个字符来完成程序,最后得到我们的最终函数。为此,我们使用前奏中的“take”功能:

short x = (take 9 . head . group) x

我们现在得到了我们想要的结果,但有一个小问题。

添加另一种情况消除错误

注意,在空列表上使用我们当前的定义会导致错误,

*> short "aaaavvvddd"
"aaaa"
*> short ""
"*** Exception: Prelude.head: empty list

由于“head”在空列表中未定义,我们需要处理另一种情况:空列表。现在我们有:

short [] = []
short x = (take 9 . head . group) x  

这是我们的“最终答案”。

【讨论】:

    【解决方案2】:

    这是另一个版本:

    short xs = take 9 $ takeWhile (== head xs) xs
    

    所以只要内容等于列表的头部(即字符串的第一个字符),我们就从列表中取出。然后我们在必要时使用take 来缩短结果。

    请注意,我们不需要为空字符串添加额外的 case,这是 Haskell 懒惰的结果:如果 takeWhile 看到 list 参数为空,它不会打扰评估条件参数,因此head xs 不会引发错误。

    【讨论】:

      【解决方案3】:

      这是一个定义:

      import Data.List (group)
      short = take 9 . head . group
      

      有趣的是,由于我们返回的字符串是原始字符串的前缀,并且长度被限制为最多 9 个字符,所以无论我们是先修剪还是最后修剪到该限制都没有关系。所以我们也可以使用这个定义:

      short = head . group . take 9
      

      这两个都是以“pointfree”风格编写的,没有提到缺少标点符号,而是缺少不必要的变量。我们也可以把定义写成

      short s = take 9 (head (group s))
      

      或者,使用$ 去掉括号:

      short s = take 9 $ head $ group s
      

      唯一的其他步骤是仅提取第一个匹配字符块,这就是 head . group 所做的(相当于您的 chomp 函数)。

      来自the docs

      group :: Eq a => [a] -> [[a]]
      

      group 函数接受一个列表并返回一个列表列表,使得结果的串联等于参数。此外,结果中的每个子列表仅包含相等的元素。例如,

      group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]
      

      这是groupBy 的一个特例,它允许程序员提供他们自己的相等性测试。

      【讨论】:

        猜你喜欢
        • 2017-11-11
        • 2011-04-28
        • 2019-10-04
        • 1970-01-01
        • 1970-01-01
        • 2014-11-14
        • 1970-01-01
        • 2011-01-08
        • 1970-01-01
        相关资源
        最近更新 更多