yes*_*era 2 string haskell list
我想在输入字符串中重复每个连续字符多于前一个字符,从第一个字符的单个匹配开始:
例如
rep "abcd" == "abbcccdddd"
Run Code Online (Sandbox Code Playgroud)
我做了这个代码,但这不起作用,String但为Int和产生正确的结果Char.
rep [] =[]
rep (x:xs) =[ (x:xs)!!y| y<-[0..(length xs)] , _<- [1..y+1]]
Run Code Online (Sandbox Code Playgroud)
我怎样才能解决这个问题?
您可以首先zip列出[1..]您的列表,然后应用replicate和concat结果:
rep xs = concatMap (uncurry replicate) $ zip [1..] xs
Run Code Online (Sandbox Code Playgroud)
示例运行:
Prelude> let rep xs = concatMap (uncurry replicate) $ zip [1..] xs
Prelude> rep "abcd"
"abbcccdddd"
Run Code Online (Sandbox Code Playgroud)
这个想法很简单,我们将每个元素与它应该重复的次数联系起来.
该zip函数具有类型[a] -> [b] -> [(a, b)],因此它需要两个列表并返回一个对列表,其中第一个元素来自第一个列表,第二个元素来自第二个列表.在我们的例子中,我们有一个结果的类型[(Int, a)]与a根据的说法.
该replicate :: Int -> a -> [a]函数采用一个表示长度和元素的整数,x并生成[x, x, x, ..., x]给定长度的列表.
该uncurry函数接受带有类型的函数a -> b -> c,即带有两个参数,并将其转换为具有类型的函数(a, b) -> c,即使用一个参数作为元组.所以uncurry replicate有类型(Int, a) -> [a].
现在类型匹配,您可以map通过ziped列表获取a [[a]]然后使用concat来连接结果.concatMap只是简写concat . map.
或者,而不是使用zip然后map你可以使用该zipWith功能:
rep xs = concat $ zipWith replicate [1..] xs
Run Code Online (Sandbox Code Playgroud)
请注意,您的解决方案似乎正常工作:
Prelude> let rep [] = []; rep (x:xs) = [ (x:xs)!! y | y <- [0..length xs], _<-[1..y+1]]
Prelude> rep [1,2,3]
[1,2,2,3,3,3]
Prelude> rep "abcd"
"abbcccdddd"
Run Code Online (Sandbox Code Playgroud)
如果您有一个不能产生正确结果的示例,请将其发布在您的问题中.
然而,这是低效的.你应该避免使用!!和length使用列表时更喜欢map和喜欢的东西fold.
此外,我不相信上述函数可以产生正确的结果,[Int]但不是因为String一个简单的原因:函数是多态的,因此通过参数化,它与列表包含的元素类型无关,它只关系它长度,结果将始终具有相同的形状(如果您看到函数永远不会"看"/"操作"元素,它只是移动它们;它完全相同的东西,独立于它们的特定类型.)