10

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)

在我使用此功能后,我打算使用它来过滤列表列表(仅将列表保留在列表中并且仅当它连续排序时)

4

6 回答 6

14

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

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

isSucc xs = and $ zipWith (<=) xs (drop 1 xs)
于 2013-03-21T08:22:40.507 回答
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
于 2013-03-21T08:25:42.467 回答
5

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

首先,我们将成对定义在许多不同情况下可能有用的功利函数:

pairwise xs = zip xs $ tail xs

或更现代的方式:

import Control.Applicative ((<*>))

pairwise = zip <*> tail

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

isSucc xs = all (\(x,y) -> succ x == y) $ pairwise xs
于 2013-03-21T12:18:56.827 回答
0

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

isIncreasingByOne :: (Eq a, Num a) => [a] -> Bool isIncreasingByOne = all (==1) (zipWith (-) (tail xs) xs)

这适用于数字类型(因此有Num a约束),包括Floatand Double。例如,如果您想检查一个序列是否一次增加超过 5 个,也很容易适应。

于 2013-03-21T17:28:13.640 回答
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)
于 2013-03-21T13:24:53.347 回答
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
于 2019-04-07T18:42:30.410 回答