2011-10-26 75 views
2

假設我有以下列表中的列表如何產生這樣一個榜單

a = [[1 2] 
    [4 2] 
    [7 3]] 

我想產生這樣

makeRow :: [[Int]] -> [Int] 

    0 1 2 3 4 5 6 7 8 9 
[-1 0 0 -1 0 0 -1 0 0 0] 

列表,以便該列表將有開始於2 0索引1,2從索引4開始,再從索引7開始索引爲0的3個0。沒有0的地方默認爲-1

+1

你是什麼具體問題?您是要求我們爲您編寫代碼,還是僅僅提供一些關於實現您所描述內容的一般提示? – NickLH

+1

@秦,你有什麼嘗試? –

+0

我的直覺告訴我,我應該使用列表理解,但不能過濾掉。 – nobody

回答

2

所以,你絕對可以使用列表理解,但這裏有一個刺。

import Data.List 

makeRow :: [[Int]] -> [Int] 
makeRow arr = place tabulate length 
       where tabulate = foldl' expand [] arr 
        expand st [idx,num] = st++[idx..(idx+num-1)] 
        length = last tabulate 

place :: [Int] -> Int -> [Int] 
place rules l = foldr ins [] [0..l] 
       where ins i st = if elem i rules then 0:st else (-1):st 

因此,makeRow首先將規則擴展爲應該設置爲-1的索引列表。然後,將循環放置在每個索引上,如果它位於我們擴展的規則列表中,則會添加0,否則會添加-1。

*Main> makeRow [[1,2],[4,2],[7,3]] 
[-1,0,0,-1,0,0,-1,0,0,0] 

我很想看到有人在列表理解中試試這個。我確信有更多優雅的方法可以做到這一點,但這樣做可以完成工作。我將把它作爲OP的一個練習,以便弄清楚如何更少地寫這些。

(一襯版)

import Data.List 

makeRow :: [[Int]] -> [Int] 
makeRow arr = [if any (\[i,n] -> elem a [i..(i+n-1)]) arr 
       then 0 else -1 | a <- [0..((sum $ last arr)-1)] ] 

我保持像製作這個功能的一個班輪是不是一個偉大的實踐技巧,交易可讀性。不過,我仍然抱着一個真正的嚮導會給我一個更簡潔的方法的希望。

+0

meh,正在尋找一個班輪 – nobody

+0

已更新的答案,但我認爲第一個更具可讀性。 –

0

這一個更短,可能更容易理解。儘管如此,仍然沒有列表理解。 ;-)

makeRow = go 0 
    where go _ [] = [] 
     go i ([j,n]:xs) = replicate (j-i) (-1) ++ replicate n 0 ++ go (j+n) xs 

您需要添加錯誤檢查和消毒的輸入,如果沒有保證所需的字段不會重疊,或者說,他們是爲了。

0

你知道如何使用非Haskell語言生成這樣的列表嗎?根據你所做的事情,將while循環轉換爲尾遞歸函數可能會相當直接。 (結果可能不會在大多數情況下,完全地道的,但知道如何實現這些轉換是非常有用)

0

肯定不是最簡潔的方法,但我覺得這是非常可讀和直接

makeRow :: [[Int]] -> [Int] 
makeRow []   = [] 
makeRow ([0,n]:pairs) = replicate n 0 ++ makeRow (map (decrementBy n) pairs) 
makeRow pairs   =   -1 : makeRow (map (decrementBy 1) pairs) 
    where decrementBy n [x,y] = [x-n,y]