我正在尝试定义一个functino,它找到列表中邻居号码之间的最小距离
类似的东西:
minNeighborsDistance [2,3,6,2,0,1,9,8] => 1
我的代码如下所示:
minNeighborsDistance [] = []
minNeighborsDistance (x:xs) = minimum[minNeighborsDistance xs ++ [subtract x (head xs)]]
虽然这似乎已经运行,但是一旦我输入列表,我就会收到异常错误。
我是Haskell的新手我会很感激这方面的任何帮助。
答案 0 :(得分:6)
如果您将单身人士名单传递给minNeighborsDistance
,那么
[]
,然后(x:xs)
将单个值分配给x
,将空白分配给xs
,然后head
时,它会抛出错误。此外,由于您以递归方式调用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
中的一些功能,即zipWith
,map
和drop
,则有一种更简单的方法:
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