[英]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.