首页 > 解决方案 > 编写一个函数,该函数需要通过haskell找到与给定坐标最近的位置

问题描述

我按如下方式启动此功能:

type Place = (String, Float, Float, [Int])
distanceList :: Float -> Float-> [Place] -> [Float]
distanceList _ _ [] = []
distanceList degN degE ((location, float1, float2, rainfall):place) =
sqrt((float1-degN)^2 + (float2-degE)^2) : distanceList degN degE place


minDistance :: Float -> Float-> Float -> Float -> [Float] -> Float
minDistance _ _ _ _ [] = 0
minDistance degN degE float1 float2 (x:xs)
    | x < minDistance degN degE float1 float2 xs = x
    | otherwise = minDistance degN degE float1 float2 xs



closestPlace :: Float -> Float -> [Place] -> String
closestPlace _ _ [] = " An error as occured "
closestPlace degN degE ((location, float1,  float2, rainfall):place)
    | rainfall !!0 == 0 && pythag == distance = location
    | otherwise = closestPlace degN degE place
    where
        pythag = sqrt((float1-degN)^2 + (float2-degE)^2)
        distance = minDistance degN degE float1 float2 (distanceList 
        degN degE place)

我有通过 Place 传递的测试数据。并且两个浮点数是北和东坐标,我需要使用毕达哥拉斯定理返回一个位置最近的字符串。

上面的代码运行,但是当你最接近的地方函数运行时,它永远不会通过第一部分,即错误消息,我只需要该函数来比较上面两个函数的 Pythagorus 输出并打印最接近的位置的字符串输入的坐标。

运行它的代码如下:

 demo :: Int -> IO ()
 demo 7 = putStrLn (closestPlace 55.0 (-5.3) testData)

标签: haskell

解决方案


你几乎在那里。就计算距离而言,可以进行一项观察:

如果到 A 点的距离大于到 B 点的距离,那么到 A 点的距离的平方将大于到 B 点的距离的平方。

这意味着我们可以比较它们的平方,而不是比较距离(并不必要地计算平方根),计算如下:

dist2 x1 y1 x2 y2 = (x2-x1)^2 + (y2-y1)^2

但是,您还想提取一些额外的元数据。两种常见的方法是附加排序键并在之后剥离它,或者直接使用比较函数。在这里,第二种方法会很好地工作:

closestPlace :: Float -> Float -> [Place] -> Place
closestPlace x y = minimumBy (comparing (dist2P x y))

我在这里添加了一个助手dist2P,它允许我们直接将一对点与一个地方进行比较;这很方便,因为我们可以使用comparing它自动将其应用于一对点,然后用于minimumBy查找最近的点。

dist2P :: Float -> Float -> Place -> Float
dist2P x y (_, x', y', _) = dist x y x' y'

然后,该助手将部分应用于源点。

多亏了minimumBy我们也能够 eta-reduce closestPlace,这总是很好的。

最后,我决定将函数的签名更改为 returnPlace而不是String. 为什么?好吧,如果事实证明您需要该地方的任何其他信息,您可以使用如下所示的 getter 轻松访问它:

placeName :: Place -> String
placeName (s, _, _, _) = s

同样,您的原始功能将因此被实现为两者的组合:

closestPlaceName :: Float -> Float -> [Place] -> String
closestPlaceName x y = placeName . closestPlace x y

推荐阅读