Haskell:替换字符串中的字符

时间:2018-02-02 14:12:11

标签: haskell

首先,我对haskell和函数式编程非常陌生,因此我的代码中可能会出现一些非常愚蠢的错误。

我试图用一个或多个不同的字符替换字符串中的几个字符,而不使用任何库。字符串看起来像这样" w1w1w8 / w7w1w1 // w"。我想用相应数量的数字替换每个大于1的数字和' /'十个人。

在阅读了几篇类似的帖子之后,我想出了这个:

replace x = 
    let 
        repl '/' = "1111111111"
        repl '9' = "111111111"
        repl '8' = "11111111"
        repl '7' = "1111111"
        repl '6' = "111111"
        repl '5' = "11111"
        repl '4' = "1111"
        repl '3' = "111"
        repl '2' = "11"
    in  map repl x

嗯,它没有用,我会很感激这方面的一些意见,甚至是实现目标的方法。提前谢谢。

2 个答案:

答案 0 :(得分:3)

首先,我们可以使用repl

来简化replicate功能
import Data.Char(isDigit, digitToInt)

replace x = map repl x
    where repl '/' = "1111111111"
          repl x | isDigit x && xi > 1 = replicate xi '1'
              where xi = digitToInt x
          repl x = [x]

此处repl这是一个将Char转换为String的函数。对于斜杠字符,它返回一个10 '1' s的字符串,对于isDigit x的字符,然后我们复制'1'xi次。最后一行表示所有其他字符x都转换为字符串[x]

如果我们现在使用map,我们会将[String]转换为[[String]]。这当然不是我们想要的。但我们可以使用concat :: [[a]] -> [a]将子列表连接在一起:

import Data.Char(isDigit, digitToInt)

replace x = concat (map repl x)
    where repl '/' = "1111111111"
          repl x | isDigit x && xi > 1 = replicate xi '1'
              where xi = digitToInt x
          repl x = [x]

我们还可以使用concatMap :: (a -> [b]) -> [a] -> [b],并使用 eta reduction x函数中删除replace参数:

import Data.Char(isDigit, digitToInt)

replace = concatMap repl
    where repl '/' = "1111111111"
          repl x | isDigit x && xi > 1 = replicate xi '1'
              where xi = digitToInt x
          repl x = [x]

然后为您的样本输入生成:

Prelude Data.Char> replace "w1w1w8/w7w1w1//w"
"w1w1w111111111111111111w1111111w1w111111111111111111111w"

答案 1 :(得分:3)

您的代码中存在两个问题:第一个问题是您只为/,9,8,7,6,5,3和2定义了repl。如果遇到任何问题,应该怎么做? ; 其中一件事?无论情况如何,您都需要在函数定义中添加一个案例。

另一个问题是你最终想要的是String,但map是一个从a -> b获取函数的函数和{{1}的列表并返回b [a]的列表。您的[b]函数属于repl类型,因此Char -> String的类型为map repl(而不是您想要的String -> [String])。你必须"压扁"列表列表只是一个列表。

有一个名为String -> String的前奏函数可以为你做这个;如果您不想使用预定义的功能,可以尝试自己实现。