Haskell程序在List中复制元素

时间:2012-10-31 04:50:49

标签: haskell

我是Haskell的新手。 我正在尝试编写一个程序,该程序将列表作为输入复制列表的每个元素k次,其中k =列表中元素的位置。

e.g。 replic[5,6,7]提供[[5],[6,6],[7,7,7]]

另一个条件是解决方案必须使用map函数。

到目前为止,我写的代码是:

replic [] = [] 
replic (x:xs) =  map (replicate 2 ) [x] ++ replic xs 

这会复制每个元素两次,因为replicate具有输入参数2

我需要的是replicate函数应该在连续调用中作为1 ,2 ,3输入。所以我需要一个柜台。我如何在那里使用计数器或做任何能给我元素位置的东西?

3 个答案:

答案 0 :(得分:8)

扩展Satvik,符号

[1..]

为您提供无数的数字列表。

函数zip关联允许您将两个列表合并为元组列表

zip :: [a] -> [b] -> [(a,b)]

例如

> zip [1..] [5,6,7] 
[(1,5),(2,6),(3,7)]

此代码将列表中的每个值与其在列表中的位置相关联

现在

replicate :: Int -> a -> [a]

重复一次任意次数的值。鉴于这两个组件,我们可以设计一个简单的函数

replic xs = map (\(a,b) -> replicate a b) (zip [1..] xs)

我会将pointfree写成

replic :: [a] -> [[a]]
replic = map (uncurry replicate) . zip [1..]

这完全符合您的要求

> replic [5,6,7]
[[5],[6,6],[7,7,7]]

答案 1 :(得分:3)

有很多方法可以做到这一点

这是一个类似于您尝试的解决方案。使用列表[1..]压缩列表会为您提供所需的计数器。

replic = repl . zip [1..]

repl [] = []
repl ((x,y):xs)  = (replicate x y) : (repl xs)

仅使用map

的另一种解决方案
replic = map f . zip [1..]
    where
        f (c,l) = replicate c l

如果您不想使用zip,也可以使用mapAccumL

import Data.List

replic = snd . mapAccumL f 1
    where
        f a v = (a+1,replicate a v)

答案 2 :(得分:1)

通常你会写:

replic = zipWith replicate [1..]

现在,您可以使用zipWith编写自己的map

zipWith' f xs ys = map (uncurry f) $ zip xs ys

请注意,您不一定需要索引,例如

import Data.List

replic xs = reverse $ transpose (tail $ inits $ reverse xs)

使用显式递归时,您可以使用map执行类似的操作:

replic = f . map return where
  f [] = []
  f (x:xs) = x : f (map (\(x:xs) -> x:x:xs) xs)