如何一次性获取列表中满足断言条件的元素及其索引?
同时获取满足断言的元素及其索引的Haskell实现
好问题!在Haskell的标准库中,确实没有直接返回满足断言的元素及其对应索引的现成函数,但我们可以通过两种简单的方式实现这个需求:要么利用现有标准库函数组合,要么手动写递归实现。
方法一:用标准库函数组合(简洁高效)
我们可以先通过zip [0..]把列表的每个元素和它的索引配对,之后再用filter筛选出满足条件的配对。这样只需要一次遍历列表,比你原来先找索引再取元素的两次遍历更高效。
示例代码:
-- 给列表元素配上从0开始的索引 addIndices :: [a] -> [(Int, a)] addIndices = zip [0..] -- 过滤出满足断言的(索引,元素)对 filterWithIndices :: (a -> Bool) -> [a] -> [(Int, a)] filterWithIndices pred = filter (pred . snd) . addIndices
用你给出的列表测试:
list :: [Int] list = [3,2,4,1,9] -- 调用函数 result = filterWithIndices (>2) list -- 输出结果:[(0,3), (2,4), (4,9)]
方法二:手动递归实现(直观易懂)
如果你想更清楚地理解底层逻辑,可以写一个递归函数,从索引0开始遍历列表,遇到满足条件的元素就将其索引和元素加入结果列表:
filterWithIndices' :: (a -> Bool) -> [a] -> [(Int, a)] filterWithIndices' pred = go 0 where go _ [] = [] -- 空列表直接返回空 go idx (x:xs) | pred x = (idx, x) : go (idx + 1) xs -- 满足条件,保留并继续遍历 | otherwise = go (idx + 1) xs -- 不满足,跳过当前元素
同样用你的列表测试,得到的结果和方法一完全一致。
对比你原来的实现
你原来的方法需要两次遍历列表:一次用findIndices找索引,一次通过列表推导式取元素。而上面的两种方法都只需要一次遍历,在处理大型列表时性能会更优,同时代码也更简洁直观。
内容的提问来源于stack exchange,提问作者Stéphane Laurent
相关产品推荐
相关产品推荐

