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)
在我使用此功能后,我打算使用它来过滤列表列表(仅将列表保留在列表中,并且只有在连续订购时才会这样)
答案 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
约束),包括Float
和Double
。如果你想要检查一个序列一次增加超过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