假設我有一個串列:
[1, 2, 1.2, 1.8, 1.3, 1.7, 1.35, 1.65...]
顯然,一個元素與其前身之間的絕對差異變得越來越小。我正在尋找一個函式來回傳串列中的第一個值,該值與其前任的絕對差等于或小于某個值。
定義應該是:
approx :: Rational -> [Rational] -> Rational
其中第一個引數是所需的絕對差異,第二個引數是給定的串列。例如:
approx 0.4 [1, 2, 1.2, 1.8, 1.3, 1.7, 1.35, 1.65...]
這應該回傳1.7。
我對 Haskell 很陌生。這就是為什么我很難進入函式式編程的心態。我的想法是洗掉串列的第一項,只要與下一項的絕對差異不等于或低于所需值,否則回傳第二個值。我怎樣才能把這個想法帶到 Haskell 中?
uj5u.com熱心網友回復:
正如評論中所建議的,您需要使用自己的尾部壓縮串列。
假設lst是[1, 2, 1.2, 1.8, 1.3, 1.7, 1.35, 1.65]:
zip lst (tail lst)
產量:
[(1.0,2.0),(2.0,1.2),(1.2,1.8),(1.8,1.3),(1.3,1.7),(1.7,1.35),(1.35,1.65)]
想要每個元組的第二個元素,以及兩個值之間的差異。我們將使用map.
map (\(f, s) -> (s, abs (f - s))) $ zip lst (tail lst)
產量:
[(2.0,1.0),(1.2,0.8),(1.8,0.6000000000000001),(1.3,0.5),(1.7,0.3999999999999999),(1.35,0.34999999999999987),(1.65,0.2999999999999998)]
現在我們只需要找到滿足條件的第一個元素。讓我們定義一個可以做到這一點的函式。我們將使用該Maybe型別,因為我們可能找不到滿足謂詞的任何內容。
findFirst :: (t -> Bool) -> [t] -> Maybe t
findFirst pred [] = Nothing
findFirst pred (x:xs) = if pred x then Just x else findFirst pred xs
現在:
findFirst (\(val, diff) -> diff <= 0.4) $ map (\(f, s) -> (s, abs (f - s))) $ zip lst (tail lst)
產生以下結果,您只需要提取您需要的資料并將所有這些邏輯封裝在一個函式中。
Just (1.7,0.3999999999999999)
作為額外的步驟,我們可以修飾findFirst使findFirstAndTransform.
findFirstAndTransform :: (t -> Bool) -> (t -> a) -> [t] -> Maybe a
findFirstAndTransform f t [] = Nothing
findFirstAndTransform f t (x:xs) = if f x then Just (t x) else findFirstAndTransform f t xs
現在當我們評估:
findFirstAndTransform (\(val, diff) -> diff <= 0.4) fst $ map (\(f, s) -> (s, abs (f - s))) $ zip lst (tail lst)
我們得到:
Just 1.7
uj5u.com熱心網友回復:
答案是:
approx eps list=snd (head (filter (\(x,y)-> abs(x-y) <= eps) (zip list (tail list))))
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/389043.html
