我需要编写一个函数来查找列表中某个特定元素的位置。我是这样写的:
findPos list elt | list == [] = -1
| head list == elt = 0
| otherwise = 1 + (findPos (tail list) elt)但是在元素在列表中重复的情况下该怎么办呢?例如:list= [2,4,9,4,8]和I想要元素"4“的位置,然后有2个位置:第二个和第四个。怎么会是一个简单的函数呢?
发布于 2011-06-12 21:08:42
对于匹配的元素,您应该返回延迟计算的索引列表。
这样做的简单方法是首先使用zip [0..]对列表进行索引,然后在第二个元素上过滤压缩后的列表,最后删除第二个元素以保留索引。
-- first version
findPos list elt = map fst $ filter ((elt==).snd) $ zip [0..] list
-- second version, using list comprehensions
findPos list elt = [index | (index, e) <- zip [0..] list, e == elt]发布于 2011-06-12 21:06:50
你可以让它返回一个索引列表。要实现这一点,您需要更改函数中的几项内容:
findPos,因为这更像是递归调用findPos并将1加到结果中,所以你应该创建一个接受计数器的辅助函数(从0开始),并将计数器增加1。但是,这个功能已经存在于Data.List中,并被称为elemIndices。因此,除非这是一个纯粹的学习练习或家庭作业,否则您根本不需要重新实现它。
发布于 2011-06-13 03:47:40
您还可以使用折叠:
findPos :: Eq a => a -> [a] -> [Int]
findPos elem = reverse . fst . foldl step ([],0) where
step (is,i) e = (if e == elem then i:is else is, succ i) 在命令式语言中,以一种感觉像while循环的方式编写代码是可能的,但却相当冗长:
findPos elem list = reverse $ thrd $ until finished step (list,0,[]) where
finished (x,_,_) = null x
step (e:es, c, acc) = (es, succ c, if e == elem then c:acc else acc)
thrd (_,_,x) = x https://stackoverflow.com/questions/6322053
复制相似问题