首次嘗試
首先,當前的模式:
fFindMinMax [(_, x, y, z)] = ...
意味着如果你傳遞一個清單,一個元素,它將只工作。因此,從傳遞一個空列表或包含兩個或更多元素的列表開始,這將失敗。
你需要的是一個map
來獲得元組的所有第二/第三/第四元素。我們可以做到這一點:
fFindMinMax cs = ...
where cSnd = map (\(_,x,_,_) -> x) cs
cThr = map (\(_,_,y,_) -> y) cs
cFou = map (\(_,_,_,z) -> z) cs
所以,現在的問題是:什麼我們應該寫爲功能謂詞。實際上,您已經嘗試了一下:我們可以計算每個座標的minimum cSnd
和maximum cSnd
等等。所以:
fFindMinMax cs = (minimum cSnd, maximum cSnd, minimum cThr, maximum cThr, minimum cFou, maximum cFou)
where cSnd = map (\(_,x,_,_) -> x) cs
cThr = map (\(_,_,y,_) -> y) cs
cFou = map (\(_,_,_,z) -> z) cs
現在是什麼類型的功能?我們沒有給我們限制Double
,我們也沒有確保所有座標具有相同的類型,fFindMinMax
類型簽名可以是:
fFindMinMax :: (Ord x, Ord y, Ord z) => [(a, x, y, z)] -> (x, x, y, y, z, z)
fFindMinMax cs = (minimum cSnd, maximum cSnd, minimum cThr, maximum cThr, minimum cFou, maximum cFou)
where cSnd = map (\(_,x,_,_) -> x) cs
cThr = map (\(_,_,y,_) -> y) cs
cFou = map (\(_,_,_,z) -> z) cs
請注意,如果你給它這個程序會出錯一個空列表,因爲沒有定義空列表的minimum
或maximum
。
改善內存消耗
與上述解決方案的問題是,我們構造列表與所述第二,第三和第四元件。由於我們沒有同時計算最小值和最大值,這意味着我們最終會將這些列表存儲到內存中。
我們可以通過編寫計算minimum
和maximum
同時對同一列表中的輔助函數提高代碼:
{-# LANGUAGE BangPatterns #-}
minmax :: Ord a => [a] -> (a,a)
minmax [] = error "Empty list"
minmax (h:t) = minmax' h h t
where minmax' a b [] = (a,b)
minmax' !a !b (c:cs) = minmax' (min a c) (max b c) cs
請問這個函數的工作?那麼第一行比較簡單:如果給出一個空列表,我們不能計算最小或最大值,所以我們提出一個錯誤空列表。在後一種情況下,該清單具有第一項h
和其餘項目t
。我們認爲h
是迄今爲止獲得的最小值和最大值:如果列表包含單個元素,則該元素既是該列表的最小值,也是最大值。所以我們調用一個額外的功能minmax' :: Ord a => a -> a -> [a] -> a
,通過給它最小值和最大值(h
和h
)和剩下的列表來計算最小值和最大值。
每次迭代時,將採取的下一個元素c
並且與迄今最小a
和下一個元素c
計算最小通過計算min
,且與迄今最大b
和下一個元素c
計算最大。我們繼續迭代,直到我們到達列表的末尾。在那種情況下,迄今爲止獲得的最小值和最大值是最終的最小值和最大值。所以我們可以將它們返回爲(a,b)
。
然後我們可以使用的功能等:
fFindMinMax :: (Ord x, Ord y, Ord z) => [(a, x, y, z)] -> (x, x, y, y, z, z)
fFindMinMax cs = (xmi, xma, ymi, yma, zmi, zma)
where (xmi, xma) = minmax $ map (\(_,x,_,_) -> x) cs
(ymi, yma) = minmax $ map (\(_,_,y,_) -> y) cs
(zmi, zma) = minmax $ map (\(_,_,_,z) -> z) cs
您打算變出你的六個雙打出了什麼事情?爲什麼六個而不是四十二個? –
它是一組座標(id,x,y,z)。因此,我想提取每個x,y和z的最小值和最大值,並將其值設置爲6. –
編譯器應該如何知道它是一組座標而不是一組字符串?它無法讀懂你的想法。您使用類型來傳達這些信息。座標值的類型是什麼? –