[英]Is there a way to use "<=" for pattern matching in Haskell?
我有以下代碼,它刪除列表中的每個第 n 個元素。
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys 0 = []
f ys 1 = []
f [] m = []
f (y:ys) n = y : (f ys (n-1))
我想讓它更短一點,並且想知道是否有辦法在模式匹配中使用“<=”。 我嘗試使用where
子句來執行此操作,但它不起作用,為什么?
f ys m = []
where
m <= 1 || ys == []
我怎樣才能逃避這種冗余? 有沒有一種在模式匹配中使用“小於或等於”的好方法?
編輯:我用警衛試過這個
where
f ys m
| m <= 1 || null ys = []
| otherwise = (head ys) : (f (tail ys) (n-1))
您可以與警衛一起工作:
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys i | i <= 1 = []
f [] _ = []
f (y:ys) n = y : (f ys (n-1))
如果滿足守衛中的條件,則該子句“觸發”,因此在這種情況下將返回一個空列表[]
。
但是,您將陷入無限循環,因為您編寫了f xs n ++ dropEvery (n xs) n
但drop 3 []
將返回[]
,因此它將繼續使用空列表調用dropEvery
。
您可以使用遞歸,我們每次遞減n
直到它達到0
,然后我們進行兩跳,所以:
dropEvery :: Int -> [a] -> [a]
dropEvery n = go (n-1)
where go _ [] = []
go i (x:xs)
| i <= 0 = go (n-1) xs
| otherwise = x : go (i-1) xs
我們還可以使用splitAt:: [a] -> ([a], [a])
和模式保護:
dropEvery n [] = []
dropEvery n ds
| (_:ys) <- sb = sa ++ dropEvery n ys
| otherwise = sa
where (sa, sb) = splitAt (n-1) ds
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.