我是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
输入。所以我需要一个柜台。我如何在那里使用计数器或做任何能给我元素位置的东西?
答案 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)