首页 > 解决方案 > 如何将数字作为字符串添加到haskell中的字符串

问题描述

我正在尝试加密字符串“aaaabbccdeee”被转换为“a4bbccde3”

我无法让它在一个功能中工作

工作解决方案1:

import Data.List (group)
gab0 :: [Char] -> [(Char, Int)]
gab0 = map(\l@(x:xs) -> (x, length l)) . group

gab1 :: (Char, Int) -> String
gab1 (d, 1) = [d]
gab1 (d, 2) = [d] ++ [d]
gab1 (d, x) = [d] ++ show x


gab :: [(Char, Int)] -> String
gab = foldr(\x acc ->  gab1 x ++ acc) [] 

{-
 - gab $ gab0 ['a', 'a', 'a', 'b', 'c', 'c','c','c','d','e','e']
"a3bc4de2"
-}

解决方案 2 不起作用:

gab2 :: [Char] -> Int -> [Char]
gab2 [x] n 
    | n > 1 = [x] ++ show n
    | otherwise = [x]
gab2 (x:y:xs) n
    | x == y = gab2 (x:xs) (n + 1)
    | otherwise = getnum x :  gab2 (y:xs) 0 
    where getnum a = [a] ++ show n ++ []

“aaaabbccdeee”转换为“a4bbccde3”

标签: haskell

解决方案


听起来你正试图将你的第一个定义压缩成一个函数——即你只需要改变一些工作代码。Haskell 在这方面做得很好。

我个人会保持gab1分开,因为它有几个特殊情况。通常它会写成咖喱形式

gab1 :: Char -> Int -> String
gab1 d 1 = [d]
gab1 d 2 = [d,d]
gad1 d x = [d] ++ show x

gab0构建一(Char,Int)对时,它唯一被使用的就是传递给gab1以后。所以我们可以融合该层:

gab0 :: String -> [String]
gab0 = map (\l@(x:_) -> gab1 x (length l)) . group

现在,由于我们已经将应用程序gab1移至gab0(天哪,这些需要一些更好的名称,是吗?),gab已简化为:

gab :: [String] -> String
gab = foldr (\x acc -> x ++ acc) [] 
    = foldr (++) []
    = concat

(我使用链式=表示连续多次减少 - 在实际代码中您需要选择一个,但它们都是等价的)。

既然如此gab简单,我们为什么不把它作为其中的一部分gab0呢?

gab0 :: String -> String
gab0 = concat . map (\l@(x:_) -> gab1 x (length l)) . group

我们可以将其gab1移入一个where子句,因为它仅用于有限的范围。我要将它重命名为renderRun,因为它将“运行”转换为字符串。

gab0 :: String -> String
gab0 = concat . map (\l@(x:_) -> renderRun x (length l)) . group
    where
    renderRun d 1 = [d]
    renderRun d 2 = [d,d]
    renderRun d x = [d] ++ show x

这更合你的胃口吗?


推荐阅读