如何解决Haskell程序,用于查找元素在列表中的位置
| 我需要编写一个函数来查找列表中一个特定元素的位置。 我是这样写的:findPos list elt | list == [] = -1
| head list == elt = 0
| otherwise = 1 + (findPos (tail list) elt)
但是如果元素在列表中重复出现,该怎么办?
例如:list= [2,4,9,8]
,我想要元素\“ 4 \”的位置,然后有2个位置:第二和第四。一个简单的功能将如何呢?
解决方法
您应该为匹配的元素返回索引的延迟评估列表。
简单的功能方法是先使用ѭ2索引列表,然后在第二个元素上过滤该压缩列表,最后删除第二个元素以保持索引。
-- 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]
, 您可以使其返回索引列表。要使此工作正常进行,您需要在函数中进行一些更改:
而不是-1,而是返回空情况的空列表(无论如何,返回-1都是一个坏习惯,您应该返回Maybe,因为这样做更有意义)。
而不是递归调用findPos
并将结果加1,您应该创建一个带有计数器(从0开始)的助手函数,并将计数器增加1。
当找到元素时,应该返回计数器的当前值,而不是返回0,而计数器的当前值是返回到列表尾部递归结果的(计数器增加)。
但是,此功能已存在于ѭ5中,并称为elemIndices
。因此,除非这是纯粹的学习练习或家庭作业,否则您根本不需要重新实现。
, 您还可以使用折叠:
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,[]) where
finished (x,_,_) = null x
step (e:es,c,acc) = (es,succ c,if e == elem then c:acc else acc)
thrd (_,x) = x
, 我认为最好的答案是来自克鲁。
如果此元素在列表中,我建议另一个想法来查找元素的第一个位置(不是所有位置)。
假设元素在列表中:
indexOf elt list = length $ takeWhile (/=elt) list
该列表从elt的开始到第一次出现时遍历,但在找到elt时停止。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。