学习Haskell:字符串操作问题

BM.*_*BM. 5 string haskell

如何在Haskell中编写一个函数,它采用格式为a1a2a3的输入字符串并扩展为a1a2a2a3a3a3.例如,输入字符串"code"将扩展为"coodddeeee"

Jon*_*FTW 19

所以你希望nth角色重复n一次.

f :: String -> String
f x = concatMap g  (zip x [1..])
   where
       g (x,y) = replicate y x
Run Code Online (Sandbox Code Playgroud)

我确信有一种更简单的方法可以做到这一点.

说明:首先我们得到字符串并将其与列表中的位置配对(从1开始).这是zip的作用:

Prelude> zip "code" [1..]
[('c',1),('o',2),('d',3),('e',4)]
Run Code Online (Sandbox Code Playgroud)

现在该函数g (x,y)使用复制函数,它复制你想要的任何y次.所以我们复制x,y次.

Prelude> g ('z',4)
"zzzz"
Run Code Online (Sandbox Code Playgroud)

如果我们将这个函数映射到生成的列表上,你会得到结果:

Prelude> map g $ zip "code" [1..]
["c","oo","ddd","eeee"]
Run Code Online (Sandbox Code Playgroud)

如果您有一个字符串列表,可以使用它们将它们连接在一起concat.concatMap将函数g应用于每对字母和数字,然后将字符串连接到最终结果.

Prelude> concat $ map g $ zip "code" [1..]
"coodddeeee"
Run Code Online (Sandbox Code Playgroud)

基本上:concat $ map g- >concatMap g

编辑:现在它工作,它也可以在一行中完成:

f x = concatMap (\(a,b)->replicate b a ) $ zip x [1..]
Run Code Online (Sandbox Code Playgroud)

输出:

Prelude> f "lambda"
"laammmbbbbdddddaaaaaa"
Run Code Online (Sandbox Code Playgroud)

  • 简短版:`f = concat.zipWith replicate [1 ..]` (23认同)
  • 我用`uncurry替换`g`.翻转复制`.做同样的事情,但使用标准的Haskell库函数. (2认同)
  • sdcvvc应该发表他的评论作为答案 - 这对我来说真的是最清楚的方式. (2认同)
  • trinithis:如果你在32位机器上有一个长度为== maxBound :: Int的字符串,那么将该函数应用于该字符串的结果将是1 + 2 + 3 + ... + 2147483647 = 2305843太字节 - 假设为1每个字符的字节数并忽略列表开销.幸运的是Haskell很懒,所以你可能不需要一次性分配它,虽然你仍然需要等待很长时间才能走到最后:-) (2认同)

Edw*_*ETT 15

import Control.Monad
f = zip [1..] >=> uncurry replicate
Run Code Online (Sandbox Code Playgroud)

产量

Main> f "code"
"coodddeeee"
Run Code Online (Sandbox Code Playgroud)


ken*_*ytm 9

可能非常低效:)

f :: Int -> [Char] -> [Char]
f _ [] = []
f n (c:s) = (replicate n c) ++ (f (n+1) s)

g :: [Char] -> [Char]
g s = f 1 s
Run Code Online (Sandbox Code Playgroud)

.

*Main> g "code"
"coodddeeee"
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考:并列比@ @更紧密地绑定,所以你可以删除一些过于偏执的括号.fn(c:s)=复制nc ++ f(n + 1)s (5认同)