假設:一組是排序列表在這裏。
您的代碼的工作原理如下:
inter :: [Int] -> [Int] -> [Int]
inter [] _ = []
inter _ [] = []
inter (x:xs) (y:ys) | (x == y) = x:[] -- if x == y, we stop?
| otherwise = inter xs ys -- can we drop both elements?
頭兩行指出,「從目前的名單之一是[]
,我們回到[]
」。到現在爲止還挺好。
然後下一條線與兩名警衛一起工作。鑑於我們發現兩個頭是相等的(x == y
),我們只需返回*一個項目列表[x]
。這是不正確的:有可能在兩個尾部xs
和ys
中,仍有兩組都是項目。第二個守衛也是不正確的:如果x
不等於y
,那並不意味着我們可以扔掉這兩個元素:有可能x
仍然在尾部ys
,或者y
仍然在xs
某處。
然而,我們可以通過這兩個列表進行排序的事實來獲得一個相當有效的解決方案。在這種情況下,我們可以簡單地放棄兩者中的最小者。因爲如果ys
已排序且x < y
,我們知道ys
中的所有元素也將大於x
。
所以,一個解決方案,我建議是:
inter :: [Int] -> [Int] -> [Int]
inter [] _ = [] -- left list is empty, stop
inter _ [] = [] -- right list is empty, stop
inter [email protected](x:xs) [email protected](y:ys) | x == y = x : inter xs ys -- both head same, continue
| x < y = inter xs ya -- left less, step left
| otherwise = inter xa ys -- right less, step right
的@
是這裏的別名。 [email protected](x:xs)
意味着我們參考了整個列表xa
和頭部x
和尾部xs
。
通常一個目標是儘可能在Haskell作爲通用:現在我們必須實施列表的inter
有Int
S,String
S等不是很優雅。我們可以概括如下:
inter :: Ord a => [a] -> [a] -> [a]
inter [] _ = []
inter _ [] = []
inter [email protected](x:xs) [email protected](y:ys) | x == y = x : inter xs ys
| x < y = inter xs ya
| otherwise = inter xa ys
感謝您的幫助和解釋! inter(x:xs)ys | elem x ys = x:inter xs ys –