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 (绝对差不超过限制的

java math.floor是啥意思

13.常用API