如何使用数据列表比较和返回数据 [英] How can I compare and return data using a list of data
问题描述
我是Haskell的新手,我正在努力寻找一种使用类成员变量返回我要寻找的成员变量的方法.我有此数据:
I'm a newbie to Haskell and I'm struggling to find a way to use class member variables to return the member variable I am looking for. I have this data:
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]
]
我要做的是返回最接近给定位置的地方.到目前为止,我已经能够计算出每个位置到给定位置的距离,并且我确切地知道应该退还哪个物品,但是我不知道该怎么做.这是我到目前为止的代码;
What I'm trying to do is to return a place closest to a given location. So far I am able to calculate the distances for each place to the given location, and I know exactly which Item should be returned, but I don't know how to actually go about doing this. This is the code I have so far;
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"输出:
Typing into the console 'closestDry 51.5 (-0.1) testData' outputs:
[0.0,1.7804484,2.059126,2.3086786,3.8078866,5.946426,3.0479496]
我可以看到最近的区域必须是伦敦",顺序是给定的地点列表,因为距离是"0.0",但是如何获得这个地点给我呢?
I can see that the closest area must be "London" in order with the given list of places as the distance is '0.0', but how do I get this single Place returned to me?
我不想返回距离列表,但是我无法弄清楚如何告诉函数获得最小距离并返回对应的Place,因为它需要与其他地方进行比较. /p>
I don't want to return the list of distances, but I can't figure out how to tell the function to get the smallest distance and return that corresponding Place, since it needs to be compared to the other places.
推荐答案
closestDry
基本上是无用的混乱,因此请摆脱它.然后,让我们编写一个distanceTo
函数,该函数为您提供从坐标到位置的距离:
closestDry
is a basically-useless mess, so get rid of it. Then, let's write a distanceTo
function that gives you the distance from coordinates to a place:
distanceTo :: Float -> Float -> Place -> Float
distanceTo lat lon place = distance lat lon (north place) (east place)
现在,让我们编写一个函数,将地点与到他们的距离配对:
Now, let's write a function that pairs the places with the distances to them:
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)]
到目前为止看起来不错!
Looks right so far!
现在,我们可以使用minimumBy
,comparing
和snd
来获取元组,然后使用fst
提取位置:
Now we can use minimumBy
, comparing
, and snd
to get the tuple, and then extract just the place with 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
计算距离,如下所示:
As an alternative to having distancesTo
, you could also calculate the distances with comparing
, like this:
closestTo :: Float -> Float -> [Place] -> Place
closestTo lat lon places = minimumBy (comparing (distanceTo lat lon)) places
这样做的优点是不需要任何元组,但缺点是需要多次重新计算同一位置的距离.
This has the advantage of not needing any of the tuples, but the disadvantage of recomputing the distance for the same place multiple times.
以任何一种方式进行警告:minimumBy
是危险的部分函数,如果程序得到一个空列表,它将使您的程序崩溃;如果closestTo
得到一个空列表,则将发生该程序:
Caveat to either way: minimumBy
is a dangerous partial function, which will crash your program if it ever gets an empty list, which will happen if closestTo
gets an empty list:
λ> closestTo 51.5 (-0.1) []
*** Exception: Prelude.foldl1: empty list
如果您对此感到担心,则需要通过返回Maybe Place
来代替它,并调整代码以在输入列表为空时返回Nothing
,而不是调用minimumBy
来避免它. (IMO,这是Haskell中的疣,minimumBy
应该只返回Maybe
本身,而不必崩溃.)
If you care about that, you'd need to avoid it by returning a Maybe Place
instead, and adjusting the code to return Nothing
when the input list is empty, instead of calling minimumBy
. (IMO, this is a wart in Haskell, and minimumBy
should just return a Maybe
itself instead of having to crash.)
这篇关于如何使用数据列表比较和返回数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!