Haskell:列表中邻居号码之间的最小距离

时间:2014-07-26 22:16:23

标签: haskell

我正在尝试定义一个functino,它找到列表中邻居号码之间的最小距离

类似的东西:

minNeighborsDistance [2,3,6,2,0,1,9,8] => 1

我的代码如下所示:

minNeighborsDistance [] = []
minNeighborsDistance (x:xs) = minimum[minNeighborsDistance xs ++ [subtract x (head xs)]]

虽然这似乎已经运行,但是一旦我输入列表,我就会收到异常错误。

我是Haskell的新手我会很感激这方面的任何帮助。

4 个答案:

答案 0 :(得分:6)

如果您将单身人士名单传递给minNeighborsDistance,那么

  1. 它将无法匹配第一行中的[],然后
  2. 它会成功匹配(x:xs)将单个值分配给x,将空白分配给xs,然后
  3. 当您尝试访问空列表的head时,它会抛出错误。
  4. 此外,由于您以递归方式调用minNeighborsDistance,因此除了向空白列表传递时,您最终总是在单个列表上调用它。

答案 1 :(得分:3)

这是我想出的:

minDistance l = minimum . map abs . zipWith (-) l $ tail l

答案 2 :(得分:2)

试试这个:

minDistance list = minimum (distance list)
  where
    distance list = map abs $ zipWith (-) list (tail list)

distance计算被减去的列表的绝对值,其自身移位1个位置:

  [2,3,6,2,0,1,9,8] -- the 8 is skipped but it does not make a difference
- [3,6,2,0,1,9,8]
= [1,3,4,2,1,8,1]

minDistance现在只获取结果列表中的最小元素。

答案 3 :(得分:2)

您的问题有点不清楚(类型签名在这里真的有帮助),但是如果您想要计算列表中相邻元素之间的差异,那么找到这些数字的最小值,我会说最明确的方法是使用一些额外的模式匹配:

-- Is this type you want the function to have?
minNeighborsDistance :: [Int] -> Int
minNeighborsDistance list = minimum $ go list
    where
        go (x:y:rest) = (x - y) : go (y:rest)
        go anythingElse = []        -- Or just go _ = []

但是,这并没有给你你想要的答案,因为当你从-4转到6时,你的示例列表的实际最小值为2。但这是一个简单的解决方法,只需应用abs

minNeighborsDistance :: [Int] -> Int
minNeighborsDistance list = minimum $ go list
    where
        go (x:y:rest) = abs (x - y) : go (y:rest)
        go anythingElse = []

我使用辅助函数来计算元素之间的差异,然后顶级定义在该结果上调用minimum以获得最终答案。

如果您使用Prelude中的一些功能,即zipWithmapdrop,则有一种更简单的方法:

minNeighborsDistance :: [Int] -> Int
minNeighborsDistance list
    = minimum        -- Calculates the minimum of all the distances
    $ (maxBound:)    -- Ensures we have at least 1 number to pass to
                     -- minimum by consing the maximum possible Int
    $ map abs        -- Ensure all differences are non-negative
    -- Compute the difference between each element.  I use "drop 1"
    -- instead of tail because it won't error on an empty list
    $ zipWith (-) list (drop 1 list)

因此合并为一行而没有评论:

minNeighborsDistance list = minimum $ (maxBound:) $ map abs $ zipWith (-) list $ drop 1 list