Haskell:返回与其前任的绝对差等于或小于某个值的列表项
Posted
技术标签:
【中文标题】Haskell:返回与其前任的绝对差等于或小于某个值的列表项【英文标题】:Haskell: Return the item of a list which absolute difference to its predecessor is equal or smaller than a certain value 【发布时间】:2022-01-16 09:58:30 【问题描述】:假设我有一个列表:
[1, 2, 1.2, 1.8, 1.3, 1.7, 1.35, 1.65...]
显然,一个元素与其前一个元素之间的绝对差异变得越来越小。我正在寻找一个函数来返回列表中的第一个值,该值与其前任的绝对差等于或小于某个值。
定义应该是:
approx :: Rational -> [Rational] -> Rational
其中第一个参数是所需的绝对差,第二个是给定的列表。例如:
approx 0.4 [1, 2, 1.2, 1.8, 1.3, 1.7, 1.35, 1.65...]
这应该返回1.7
。
我对 Haskell 很陌生。这就是为什么我很难进入函数式编程的心态。我的想法是删除列表的第一项,只要与下一项的绝对差不等于或低于所需值,否则返回第二个值。如何将这个想法融入 Haskell?
【问题讨论】:
提示:zip lst (tail lst)
将为您提供所有相邻对的列表。因为它是惰性的,所以它不会生成您实际上不需要查看的对。使用它来构造(y, abs (x-y))
对的列表,其中(x,y)
是相邻的对。
投票结束。需要细节和清晰度。
我知道zip lst (tail lst)
会给我一个类似[(1,2),(2,1.2),(1.2,1.8)...]
的列表,但我不知道如何过滤以便满足abs(x-y)<eps
的条件,其中eps
是阈值。
试过这个:approx eps list=snd (head (filter (\(x,y)-> abs(x-y) <= eps) zip list (tail list)))
。但一定有什么地方不对劲。
【参考方案1】:
按照 cmets 中的建议,您需要使用自己的尾部压缩列表。
假设lst
是[1, 2, 1.2, 1.8, 1.3, 1.7, 1.35, 1.65]
:
zip lst (tail lst)
产量:
[(1.0,2.0),(2.0,1.2),(1.2,1.8),(1.8,1.3),(1.3,1.7),(1.7,1.35),(1.35,1.65)]
想要每个元组的第二个元素,和两个值的差值。我们将使用map
。
map (\(f, s) -> (s, abs (f - s))) $ zip lst (tail lst)
产量:
[(2.0,1.0),(1.2,0.8),(1.8,0.6000000000000001),(1.3,0.5),(1.7,0.3999999999999999),(1.35,0.34999999999999987),(1.65,0.2999999999999998)]
现在我们只需要找到第一个满足条件的元素。让我们定义一个可以做到这一点的函数。我们将使用Maybe
类型,因为我们可能找不到任何满足谓词的东西。
findFirst :: (t -> Bool) -> [t] -> Maybe t
findFirst pred [] = Nothing
findFirst pred (x:xs) = if pred x then Just x else findFirst pred xs
现在:
findFirst (\(val, diff) -> diff <= 0.4) $ map (\(f, s) -> (s, abs (f - s))) $ zip lst (tail lst)
产生以下内容,只需提取您需要的数据并将所有这些逻辑包装在一个函数中。
Just (1.7,0.3999999999999999)
作为附加步骤,我们可以修饰 findFirst
以制作 findFirstAndTransform
。
findFirstAndTransform :: (t -> Bool) -> (t -> a) -> [t] -> Maybe a
findFirstAndTransform f t [] = Nothing
findFirstAndTransform f t (x:xs) = if f x then Just (t x) else findFirstAndTransform f t xs
现在当我们评估时:
findFirstAndTransform (\(val, diff) -> diff <= 0.4) fst $ map (\(f, s) -> (s, abs (f - s))) $ zip lst (tail lst)
我们得到:
Just 1.7
【讨论】:
【参考方案2】:答案是:
approx eps list=snd (head (filter (\(x,y)-> abs(x-y) <= eps) (zip list (tail list))))
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于Haskell:返回与其前任的绝对差等于或小于某个值的列表项的主要内容,如果未能解决你的问题,请参考以下文章
[leetcode] No.1438 绝对差不超过限制的最长连续子数组
[leetcode] No.1438 绝对差不超过限制的最长连续子数组
《LeetCode之每日一题》:77.绝对差不超过限制的最长连续子数组
LeetCode 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit (绝对差不超过限制的