[英]Remove elements in list with a list of Int (Haskell)
我正在編寫函數,該函數接受一個Int
列表,一個通用類型a
列表並刪除在Int列表中具有索引的所有元素。
例如: removeEl [1,3,4] [1,2,3,4,5,6]
返回[1,3,6]
或removeEl [1,2] "Firefox"
返回"Fefox"
這是我的嘗試:
removeEl :: [Int] -> [a] -> [a]
removeEl [] xs = []
removeEl ns [] = []
removeEl (n:ns) (x:xs) | n == 0 = removeEl ns xs
| n > 0 = x:removeEl (n-1) xs
我意識到(n-1)
是一個Int
,而不是[Int]
所以它失敗了。 我需要編寫輔助功能來使用嗎?
您需要傳遞一個新列表,但是該列表中的每個項目都需要遞減,因為您已經移動了第二個參數的每個元素的位置。 無論您是否實際上已刪除head元素,這都是事實。
removeEl (n:ns) (x:xs) | n == 0 = removeEl (map pred ns) xs
| n > 0 = x:removeEl (map pred (n:ns)) xs
有很多機會可以重構它,但是我玩過的任何東西都感覺不那么簡單。
另外,您的第一個基本情況是錯誤的:索引列表中沒有項目,您想返回所有內容 ,而不是什么 都 沒有 :
remove [] xs = xs
(請記住,這僅在第一個參數單調增加時有效。)
您還可以通過列表理解來避免顯式遞歸:
removeEl ns xs = [x | (n,x) <- zip [0..] xs, not(n `elem` ns)]
我相信您的算法是O(n*m)
,其中n
是列表中元素的數量, m
是要刪除的索引的數量。 還不幸的是,必須對索引列表進行排序。 這是一個~O(n*log(m))
解決方案,不需要對索引進行排序。
import qualified Data.Set as Set
removeE1 indices xs = go 0 xs
where is = Set.fromList indices
go _ [] = []
go n (y:ys) | n `Set.member` is = go (n+1) ys
| otherwise = y : go (n+1) ys
而且,可以通過使用哈希映射來改善這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.