2012-10-31 16 views
4

我是Haskell的新手。 我想寫一個程序給出一個列表作爲輸入複製列表中的每個元素k次,其中k =元素在列表中的位置。Haskell程序複製列表中的元素

例如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。所以我需要一個櫃檯。我如何在那裏使用櫃檯或做其他任何能夠給我元素位置的東西?

回答

7

擴展在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]] 
+8

或者'replic = zipWith複製[1 .. ]' – hammar

+0

非常感謝@PhilipJF。 – apgp88

3

這樣做有

的很多方面這類似於你試圖做一個解決方案。用清單012壓縮清單[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) 
+0

@AmolPatil見改進方案 – Satvik

+0

非常感謝@satvik – apgp88

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)