我们考虑两个列表:["a","b","c"]
和["a","b","c","d","e","f"]
我想检查第一个列表是否是另一个列表的开头 我以为我可以用:
["a","b","c"] == head (splitAt (length ["a","b","c"]) ["a","b","c","d","e","f"])
不幸的是,这不起作用。还有另一种方法可以将新列表中第一个3个第一个元素从列表中删除吗?
答案 0 :(得分:6)
您可以使用take
来避免遍历列表两次,而不是使用zipWith
。当您调用length
时,首先必须遍历较短的列表,然后从较长的列表中获取那么多值,然后遍历列表,逐个元素地进行比较。更有意义的是同时遍历两个列表,在较短的列表到期时停止比较。 zipWith
正好提供了此功能:
-- Definitions for `and` and `zipWith` in `Prelude`
--
-- and :: [Bool] -> Bool
-- and [] = True
-- and (x:xs) = x && and xs
--
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
-- zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
-- zipWith _ _ _ = []
sameStartingElements :: Eq a => [a] -> [a] -> Bool
sameStartingElements xs ys = and $ zipWith (==) xs ys
由于懒惰,这个定义只会遍历两个列表,并且只要其中一个列出元素就会停止。这将更有效,并且它避免了必须知道任何列表的长度。
答案 1 :(得分:3)
我想检查第一个列表是否是另一个列表的开头。
您可以使用Data.List模块中的isPrefixOf
。
答案 2 :(得分:1)
您正在寻找的功能是take
。请参阅here。