如何使用数据列表比较和返回数据 [英] How can I compare and return data using a list of data

查看:81
本文介绍了如何使用数据列表比较和返回数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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!

现在,我们可以使用minimumBycomparingsnd来获取元组,然后使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆