首先,我对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
嗯,它没有用,我会很感激这方面的一些意见,甚至是实现目标的方法。提前谢谢。
答案 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
的前奏函数可以为你做这个;如果您不想使用预定义的功能,可以尝试自己实现。