4

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

例如replic[5,6,7][[5],[6,6],[7,7,7]].

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

到现在我写的代码是:

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

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

我需要的是replicate函数应该像1 ,2 ,3连续调用一样被输入。所以我需要一个柜台。我怎样才能在那里使用计数器或做任何其他可以给我元素位置的事情?

4

3 回答 3

8

扩展 Satvik,符号

[1..]

给你一个无限的数字列表。

函数zipassociates 允许您将两个列表合并为一个元组列表

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]]
于 2012-10-31T05:08:54.763 回答
3

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

这是一个类似于您尝试做的解决方案。用 list 压缩列表[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)
于 2012-10-31T04:56:34.763 回答
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)
于 2012-10-31T09:57:17.633 回答