[英]How can I compare and return data using a list of data
我是 Haskell 的新手,我正在努力尋找一種方法來使用 class 成員變量來返回我正在尋找的成員變量。 我有這個數據:
data Place = Place {name :: String,
north :: Float,
east :: Float,
rainfall :: [Int]
} deriving (Eq, Ord, Show)
testData :: [Place]
testData = [
Place "London" 51.5 (-0.1) [0, 0, 5, 8, 8, 0, 0],
Place "Norwich" 52.6 (1.3) [0, 6, 5, 0, 0, 0, 3],
Place "Birmingham" 52.5 (-1.9) [0, 2, 10, 7, 8, 2, 2],
Place "Hull" 53.8 (-0.3) [0, 6, 5, 0, 0, 0, 4],
Place "Newcastle" 55.0 (-1.6) [0, 0, 8, 3, 6, 7, 5],
Place "Aberdeen" 57.1 (-2.1) [0, 0, 6, 5, 8, 2, 0],
Place "St Helier" 49.2 (-2.1) [0, 0, 0, 0, 6, 10, 0]
]
我想要做的是返回一個最接近給定位置的地方。 到目前為止,我能夠計算每個地方到給定位置的距離,並且我確切地知道應該返回哪個項目,但我不知道如何實際 go 這樣做。 這是我到目前為止的代碼;
closestDry :: Float -> Float -> [Place] -> [Float]
closestDry _ _ [] = []
closestDry lx ly (x:xs) = distance(lx)(ly)(north x)(east x)):closestDry lx ly xs
distance :: Float -> Float -> Float -> Float -> Float
distance x1 y1 x2 y2 = sqrt ((y1 - y2)^2 + (x1 - x2)^2)
輸入控制台“closestDry 51.5 (-0.1) testData”輸出:
[0.0,1.7804484,2.059126,2.3086786,3.8078866,5.946426,3.0479496]
我可以看到最近的區域必須是“倫敦”,因為距離是“0.0”,所以給定的地點列表必須是“0.0”,但是如何讓這個地方返回給我呢?
我不想返回距離列表,但我不知道如何告訴 function 獲得最小距離並返回相應的地方,因為它需要與其他地方進行比較。
closestDry
是一個基本上沒用的爛攤子,所以擺脫它。 然后,讓我們寫一個distanceTo
function 給出從坐標到某個地方的距離:
distanceTo :: Float -> Float -> Place -> Float
distanceTo lat lon place = distance lat lon (north place) (east place)
現在,讓我們編寫一個 function 將地點與到它們的距離配對:
distancesTo :: Float -> Float -> [Place] -> [(Place, Float)]
distancesTo lat lon = map (\place -> (place, distanceTo lat lon place))
試一試:
λ> distancesTo 51.5 (-0.1) testData
[(Place {name = "London", north = 51.5, east = -0.1, rainfall = [0,0,5,8,8,0,0]},0.0),(Place {name = "Norwich", north = 52.6, east = 1.3, rainfall = [0,6,5,0,0,0,3]},1.7804484),(Place {name = "Birmingham", north = 52.5, east = -1.9, rainfall = [0,2,10,7,8,2,2]},2.059126),(Place {name = "Hull", north = 53.8, east = -0.3, rainfall = [0,6,5,0,0,0,4]},2.3086786),(Place {name = "Newcastle", north = 55.0, east = -1.6, rainfall = [0,0,8,3,6,7,5]},3.8078866),(Place {name = "Aberdeen", north = 57.1, east = -2.1, rainfall = [0,0,6,5,8,2,0]},5.946426),(Place {name = "St Helier", north = 49.2, east = -2.1, rainfall = [0,0,0,0,6,10,0]},3.0479496)]
到目前為止看起來不錯!
現在我們可以使用minimumBy
、 compare 和snd
來獲取元組,然后使用comparing
提取fst
:
import Data.Foldable (minimumBy)
import Data.Ord (comparing)
closestTo :: Float -> Float -> [Place] -> Place
closestTo lat lon places = fst $ minimumBy (comparing snd) (distancesTo lat lon places)
讓我們嘗試一下:
λ> closestTo 51.5 (-0.1) testData
Place {name = "London", north = 51.5, east = -0.1, rainfall = [0,0,5,8,8,0,0]}
成功!
作為具有distancesTo
的替代方法,您還可以使用comparing
計算距離,如下所示:
closestTo :: Float -> Float -> [Place] -> Place
closestTo lat lon places = minimumBy (comparing (distanceTo lat lon)) places
這具有不需要任何元組的優點,但缺點是多次重新計算同一位置的距離。
對任何一種方式的警告: minimumBy
是一個危險的部分 function,如果它獲得一個空列表,它將使您的程序崩潰,如果closestTo
的列表獲得一個空列表,則會發生這種情況:
λ> closestTo 51.5 (-0.1) []
*** Exception: Prelude.foldl1: empty list
如果您關心這一點,則需要通過返回一個Maybe Place
來避免它,並調整代碼以在輸入列表為空時返回Nothing
,而不是調用minimumBy
。 (IMO,這是 Haskell 中的一個缺陷, minimumBy
應該只返回一個Maybe
本身,而不必崩潰。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.