haskell - 编写一个函数,该函数需要通过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)
解决方案
你几乎在那里。就计算距离而言,可以进行一项观察:
如果到 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
推荐阅读
- ruby-on-rails - 不确定要添加到我的路线以获取 icalendar gem 链接
- python - 自动从 excel 文件发送批量电子邮件
- flutter - Flutter 屏幕的条件渲染
- itext7 - itext7修改表格宽度
- xml - 如何从 XSLT 参数输出双引号?
- android - 以嵌套 json 格式在 kotlin 中使用 retrofit2 发送数据
- c - 为什么函数 strlen() 会为两个相同长度的 char 数组返回不同的值?
- python - System calls with google cloud scheduler and python script
- node.js - Create-react-app:未处理的错误事件:Events.js.187
- ruby-on-rails - Billing.subscription.renewed webhook 没有被触发