假設我有以下列表中的列表如何產生這樣一個榜單
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
假設我有以下列表中的列表如何產生這樣一個榜單
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
所以,你絕對可以使用列表理解,但這裏有一個刺。
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)] ]
我保持像製作這個功能的一個班輪是不是一個偉大的實踐技巧,交易可讀性。不過,我仍然抱着一個真正的嚮導會給我一個更簡潔的方法的希望。
meh,正在尋找一個班輪 – nobody
已更新的答案,但我認爲第一個更具可讀性。 –
這一個更短,可能更容易理解。儘管如此,仍然沒有列表理解。 ;-)
makeRow = go 0
where go _ [] = []
go i ([j,n]:xs) = replicate (j-i) (-1) ++ replicate n 0 ++ go (j+n) xs
您需要添加錯誤檢查和消毒的輸入,如果沒有保證所需的字段不會重疊,或者說,他們是爲了。
你知道如何使用非Haskell語言生成這樣的列表嗎?根據你所做的事情,將while循環轉換爲尾遞歸函數可能會相當直接。 (結果可能不會在大多數情況下,完全地道的,但知道如何實現這些轉換是非常有用)
肯定不是最簡潔的方法,但我覺得這是非常可讀和直接
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]
你是什麼具體問題?您是要求我們爲您編寫代碼,還是僅僅提供一些關於實現您所描述內容的一般提示? – NickLH
@秦,你有什麼嘗試? –
我的直覺告訴我,我應該使用列表理解,但不能過濾掉。 – nobody