【问题标题】:finding minumum of list of tuples in HASKELL在 HASKELL 中找到最小的元组列表
【发布时间】:2013-03-24 10:17:14
【问题描述】:

我试图找到具有最小距离((x1,x2)和(y1,y2)距离= abs(y2-y1)+abs(x2-x1)的元组(一个或多个)具有特定的点。例如:

列表将是 [(1,2),(3,4),(5,4),(5,6),(9,12) ]

具体点是(xpos,ypos)=(4,4)。

然后我的函数应该返回 [(3,4),(5,4)]。我已经尝试实现这一点,但我有一个问题,我认为它与基本情况有关。有没有人可以帮助我?

disSolver xpos ypos coor = abs (xpos - (fst coor)) +abs(ypos-(snd coor))



closestTuple _ _ [] =[]
closestTuple xpos ypos (x:y:xs) = if (disSolver xpos ypos x)<= (disSolver xpos ypos y)
then [x] ++ closestTuple xpos ypos (xs)
else closestTuple xpos ypos (y:xs)

提前致谢!

【问题讨论】:

    标签: list haskell tuples


    【解决方案1】:

    您已将disSolver 分解为它自己的函数,这很好。您可以更进一步,还可以抽象出“通过某些指定度量找到最小值”的算法。 closestTuple 只是两者的组合。 (除了我使用 leventov 的 distSolver 而不是你的 disSolver,因为这些类型更好地结合在一起。)

    我选择使用函数管道而不是显式模式匹配和递归来演示 minimaBy,因为我碰巧认为在这种情况下它更清晰且不易出错。

    还要注意我给minimaBy 的类型意味着如果它编译,它会自动没有某些错误。我们不能不小心按c 类型(对应closestTuple 的签名中的(a, a))排序,因为只有b 被声明为实现Ord

    (话虽如此,我还没有编译或以其他方式测试过这段代码,只能保证它在我的脑海中完美运行:-))

    import Control.Arrow ((&&&))
    import Data.Function (on)
    import Data.List (groupBy, sortBy)
    import Data.Maybe (fromMaybe, listToMaybe)
    import Data.Ord (comparing)
    
    minimaBy :: Ord b => (c -> b) -> [c] -> [c]
    minimaBy f = map fst
               . fromMaybe []
               . listToMaybe
               . groupBy ((==) `on` snd)
               . sortBy (comparing snd)
               . map (id &&& f)
    
    closestTuple :: (Num a, Ord a) => (a, a) -> [(a, a)] -> [(a, a)]
    closestTuple = minimaBy . distSolver
    

    文档链接:

    【讨论】:

    • 不错。虽然fromMaybe[] . listToMaybe 有点迂回。 take 1 可能不太明确,但 IMO 仍然更清晰,如此简单。
    • groupBy snd 不进行类型检查。我觉得应该是groupBy ((==) `on` snd)
    • @leftaroundabout fromMaybe [] . listToMaybe :: [[a]] -&gt; [a]take 1 :: [a] -&gt; [a]。我会使用headMay from safe 而不是listToMaybe,以使意图更清晰,但它不在Haskell 平台中。还有什么更惯用的吗?
    • @dave4420:对,concat . take 1 就是我的意思。诚然,这已经不再那么美好了。
    • 我不小心在minimaBy 中使用了the environment comonad(与the environment comonad 同构)。
    【解决方案2】:

    当要从中找到最近点的列表恰好包含 1 个元素时,您错过了这种情况。您的 closestTuple 实现的逻辑似乎也存在错误。

    这是我将如何编写函数:

    distSolver :: Num a => (a, a) -> (a, a) -> a
    distSolver (px, py) (x, y) = (abs (x - px)) + (abs (y - py))
    
    closestTuple :: (Num a, Ord a) => (a, a) -> [(a, a)] -> [(a, a)]
    closestTuple _ [] = []
    closestTuple pos (x:xs) = mins (distSolver pos x) [x] pos xs
    
    mins _ mxs _ [] = mxs
    mins minDist mxs pos (x:xs)
        | dist < minDist  = mins dist [x] pos xs
        | dist == minDist = mins dist (x:mxs) pos xs
        | otherwise       = mins minDist mxs pos xs
      where dist = distSolver pos x
    

    【讨论】:

    • 非常感谢,我意识到了我的错,但我已经发布了,所以我没有机会 :(,再次感谢。
    猜你喜欢
    • 2017-07-20
    • 2022-01-18
    • 2020-02-10
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    • 2019-04-03
    • 1970-01-01
    相关资源
    最近更新 更多