Haskell如何实现接收两个Int列表返回对应元素索引的Int列表
实现参考
已知条件
- 参考下标映射的源列表:
list1 = [14,24,1,2,11,7,23,8,12,22,20,0,15,19,4,9,10,21,18,17,3,13,16,5,6,25] - 待查询的目标列表:
list2 = [14,14,24,24,1,1,2,2] - 预期返回结果:
[0,0,1,1,2,2,3,3] - 已有的工具函数能力:
elemIndex' :: Eq a => a -> [a] -> Int elemIndex' x = fromMaybe (-1) . elemIndex x
该函数可以返回单个元素在参考列表中首次出现的下标,比如查询14在list1中的位置时返回0,查询不到元素时返回-1。
- 待实现函数要求:
类型签名固定为findIndex :: [Int] -> [Int] -> [Int],入参顺序为「参考键值列表」→「待查询元素列表」,返回值是待查询列表每个元素对应在参考列表下标的集合,支持递归实现或借助map等标准函数实现。
方案1:借助map实现(代码最简洁)
需求本质是遍历待查询列表的每一个元素,逐个调用已有的elemIndex'查询其在参考列表的下标,直接用map把查询逻辑映射到待查询列表的所有元素上即可,代码量极少:
findIndex :: [Int] -> [Int] -> [Int] findIndex refList queryList = map (\element -> elemIndex' element refList) queryList
把题目给出的list1、list2传入该函数,就能直接得到预期的[0,0,1,1,2,2,3,3]结果。如果习惯用点自由风格写代码,还可以简化成findIndex refList = map (flip elemIndex' refList),执行效果完全一致。
方案2:纯递归实现
如果不想用高阶函数,按列表递归的常规思路写就行:
- 基准边界:当待查询列表为空时,直接返回空列表作为结果
- 递归逻辑:把待查询列表拆成头部元素和剩余尾部,先计算头部元素的下标,再递归处理尾部列表,最后把当前下标和递归返回的尾部结果拼接起来
具体代码如下:
findIndex :: [Int] -> [Int] -> [Int] -- 边界条件:没有待查询元素时返回空 findIndex _ [] = [] -- 拆分待查询列表递归处理 findIndex refList (x:xs) = elemIndex' x refList : findIndex refList xs
这个版本和map版本的执行逻辑、输出结果完全一致,没有额外依赖其他函数,完全符合递归实现的要求。
补充说明:现有
elemIndex'在元素不存在时返回-1的逻辑,只要待查询列表的所有元素都在参考列表中就不会影响结果;如果后续需要处理元素不存在的异常场景,可以按需调整工具函数的返回逻辑。当前实现取元素首次出现位置的逻辑,和题目给出的示例预期完全对齐。
内容的提问来源于stack exchange,提问作者FrankZZZ
相关产品推荐
相关产品推荐

