如何使用数据列表比较和 return 数据
How can I compare and return data using a list of data
我是 Haskell 的新手,我正在努力寻找一种方法将 class 成员变量用于 return 我正在寻找的成员变量。我有这个数据:
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]
]
我想做的是 return 一个离给定位置最近的地方。到目前为止,我能够计算出每个地点到给定位置的距离,并且我确切地知道应该 returned 哪个 Item,但我不知道如何真正去做这件事。这是我目前的代码;
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]
我可以看到最近的区域必须是 "London" 以符合给定的地点列表,因为距离是“0.0”,但是我如何才能将这个地方 return 编辑到我?
我不想 return 距离列表,但我不知道如何告诉函数获取最小距离和 return 相应的地点,因为它需要和其他地方比较一下。
closestDry
基本上是无用的混乱,所以摆脱它。然后,让我们编写一个 distanceTo
函数,它可以提供从坐标到某个地方的距离:
distanceTo :: Float -> Float -> Place -> Float
distanceTo lat lon place = distance lat lon (north place) (east place)
现在,让我们编写一个函数,将地点与到它们的距离配对:
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
、comparing
和snd
来获取元组,然后只提取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
是一个危险的部分函数,如果它得到一个空列表,它会使您的程序崩溃,如果 closestTo
得到一个空列表,就会发生这种情况:
λ> closestTo 51.5 (-0.1) []
*** Exception: Prelude.foldl1: empty list
如果您关心这一点,则需要通过 returning 一个 Maybe Place
来避免它,并将代码调整为 return Nothing
输入列表为空,而不是调用 minimumBy
。 (IMO,这是 Haskell 中的一个缺陷,minimumBy
应该只是 return 一个 Maybe
本身而不是崩溃。)
我是 Haskell 的新手,我正在努力寻找一种方法将 class 成员变量用于 return 我正在寻找的成员变量。我有这个数据:
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]
]
我想做的是 return 一个离给定位置最近的地方。到目前为止,我能够计算出每个地点到给定位置的距离,并且我确切地知道应该 returned 哪个 Item,但我不知道如何真正去做这件事。这是我目前的代码;
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]
我可以看到最近的区域必须是 "London" 以符合给定的地点列表,因为距离是“0.0”,但是我如何才能将这个地方 return 编辑到我?
我不想 return 距离列表,但我不知道如何告诉函数获取最小距离和 return 相应的地点,因为它需要和其他地方比较一下。
closestDry
基本上是无用的混乱,所以摆脱它。然后,让我们编写一个 distanceTo
函数,它可以提供从坐标到某个地方的距离:
distanceTo :: Float -> Float -> Place -> Float
distanceTo lat lon place = distance lat lon (north place) (east place)
现在,让我们编写一个函数,将地点与到它们的距离配对:
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
、comparing
和snd
来获取元组,然后只提取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
是一个危险的部分函数,如果它得到一个空列表,它会使您的程序崩溃,如果 closestTo
得到一个空列表,就会发生这种情况:
λ> closestTo 51.5 (-0.1) []
*** Exception: Prelude.foldl1: empty list
如果您关心这一点,则需要通过 returning 一个 Maybe Place
来避免它,并将代码调整为 return Nothing
输入列表为空,而不是调用 minimumBy
。 (IMO,这是 Haskell 中的一个缺陷,minimumBy
应该只是 return 一个 Maybe
本身而不是崩溃。)