检查列表是否是另一个列表的子列表

时间:2017-11-10 22:51:16

标签: haskell

我想编写一个函数来检查一个列表是否是另一个列表的子列表。我写了这个,但它不起作用,但我猜需要这样的东西。谢谢你的帮助。

subList :: Eq a => [a] -> [a] -> Bool
subList _ []    = False
subList [] _    = True
subList (x:xs) (y:ys) =   
     x == y    = subList xs ys   
     otherwise = subList (x:xs) ys

2 个答案:

答案 0 :(得分:2)

您的代码即将开始工作,但只需要进行一些小的更改。正如其他人在评论中所说,你需要包含|模式保护,并从第一个函数调用中删除=。以下是最后3行应该是什么样的:

subList (x:xs) (y:ys)   
    | x == y    = subList xs ys   
    | otherwise = subList (x:xs) ys

这将大部分修复您的代码,但您还需要添加基本案例subList [] [] = True,因为空列表[]是另一个空列表{{1}的子列表},就像[][1]的子列表一样。

添加这些更改后,您的代码将如下所示:

[1]

一些示例电话:

subList :: Eq a => [a] -> [a] -> Bool
subList [] [] = True
subList _ []    = False
subList [] _    = True
subList (x:xs) (y:ys) 
    | x == y    = subList xs ys   
    | otherwise = subList (x:xs) ys

然而,他们的问题是这样的:

Prelude> subList [] []
True
Prelude> subList [1] [1,2,3]
True
Prelude> subList [1] [4,2,3]
False
Prelude> subList [1] []
False
Prelude> subList [1,2] [1,2]
True
Prelude> subList [1,2] [2,1]
False
Prelude> subList [1,2] [1,2,2,1]
True

暗示Prelude> subList [1,3] [1,2,3] True [1,3]的子列表。这可能是有意的,但如果不是,那么你需要改变你的方法。

另一种方法:

对于您的两个列表[1,2,3]xs,您可以将ys拆分为长度为ys的子列表,让我们说xs,并检查如果subys中存在xs。为此,您可以使用splitAt,它会按subys个字符拆分列表。这是一个示例函数:

n

如果您不想使用split_lists :: Int -> [a] -> [[a]] split_lists _ [] = [] split_lists n xs | length first == n = first : restxs | otherwise = restxs where (first, rest) = splitAt n xs restxs = split_lists n (tail first ++ rest) ,可以执行以下操作:

splitAt

其行为如下:

split_lists :: Int -> [a] -> [[a]]
split_lists _ [] = []
split_lists n xs = filter (\x -> length x == n) list
    where list = take n xs : split_lists n (drop 1 xs)

然后您可以使用any来检查第一个列表是否存在于拆分为子列表的第二个列表中,或者您可以使用正常的递归,由您决定。

以下是使用Prelude> split_lists 3 [1,2,3,4,5,6,7,8,9,10] [[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[7,8,9],[8,9,10]] 的示例:

any

以下是使用递归的示例:

subList :: (Eq a) => [a] -> [a] -> Bool
subList [] [] = True
subList xs ys = any (==xs) subys
    where subys = (split_lists (length xs) ys)

现在表现如下:

subList :: (Eq a) => [a] -> [a] -> Bool
subList [] [] = True
subList xs ys = check_lists xs subys
    where subys = (split_lists (length xs) ys)

check_lists :: (Eq a) => [a] -> [[a]] -> Bool
check_lists _ [] = False
check_lists xs (y:ys)
    | xs == y = True
    | otherwise = check_lists xs ys

答案 1 :(得分:2)

您可以像这样使用函数相交:

相交[list1] [list2] == [list1]

divs

您将为此导入Data.List。