检查是否连续订购列表

时间:2013-03-21 08:11:30

标签: haskell functional-programming

Haskell中是否有任何库函数允许我检查列表是否连续排序?例如。 [1,2,3,4]有效,[1,2,3,10]无效。

基本上我可以有一个范围在3到5个元素之间的列表,我正在尝试检查该列表是否连续排序。

我的尝试(我不确定这是否是接近它的正确方法,似乎是太多的重复)

isSucc:: [Integer] -> Bool
isSucc[]            = True
isSucc(x:y:zs)      = 
    if (x+1) == y
    then True && isSucc(y:zs)
    else isSucc(y:zs)

在我使用此功能后,我打算使用它来过滤列表列表(仅将列表保留在列表中,并且只有在连续订购时才会这样)

6 个答案:

答案 0 :(得分:14)

您可以使用技巧zipWith f xs (drop 1 xs)f应用于连续的列表元素对。 (注意drop 1而不是tail,因为如果列表为空则后者失败!)

如果您将f替换为<=,则会获得Bool值列表。现在看看它们是否都是True

isSucc xs = and $ zipWith (<=) xs (drop 1 xs)

答案 1 :(得分:9)

没有标准功能。

以下是您的函数的固定版本,使其成为通用版本,删除冗余条件并添加缺少的函数:

isSucc :: (Enum a, Eq a) => [a] -> Bool
isSucc [] = True
isSucc (x:[]) = True
isSucc (x:y:zs) | y == succ x = isSucc $ y:zs
isSucc _ = False

答案 2 :(得分:5)

我更喜欢使用比MathematicalOrchid提供的解决方案更易读的解决方案。

首先,我们将定义在许多不同情况下可能有用的实用函数 pairwise

pairwise xs = zip xs $ tail xs

或以更现代的方式:

import Control.Applicative ((<*>))

pairwise = zip <*> tail

然后将其与其他组合器一起使用:

isSucc xs = all (\(x,y) -> succ x == y) $ pairwise xs

答案 3 :(得分:0)

还有另外一种方式,

isOrdered :: (Enum a, Eq a) => (a -> a -> Bool) -> [a] -> Bool
isOrdered op (a:b:ls) = op a b && isOrdered op (b:ls)
isOrdered op _ = True

因此,

isSucc = isOrdered ((==) . succ)

答案 4 :(得分:0)

如果要检查所有连续差异是否等于1,可以使用

isIncreasingByOne ::(Eq a,Num a)=&gt; [a] - &gt;布尔    isIncreasingByOne = all(== 1)(zipWith( - )(tail xs)xs)

这适用于数字类型(因此Num a约束),包括FloatDouble。如果你想要检查一个序列一次增加超过5个,那么它也很容易适应。比如说。

答案 5 :(得分:0)

-检查是否订购

isordd:: [Int] -> Bool 
isordd [] = True
isordd (x:y:xs) 
 | x > y = False
 | lengh xs == 0 = True
 | otherwise = isordd (y:xs)

-计算列表的长度

lengh::[Int]->Int
lengh [] = 0
lengh (x:xs) = 1+lengh xs