You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中如何从列表按多个指定索引选取对应元素

Haskell按索引列表提取目标元素的实现

你已经掌握的单索引取值写法可以直接扩展到多索引场景,不需要照搬命令式语言的循环逻辑,也完全可以用filter实现,两种方案的行为有明显区别,按需选择即可:

直接映射索引的写法

你原来用的head (drop idx myList)本身就是纯函数,只要把这个逻辑应用到索引列表的每一项上就能得到结果,Haskell里用map就能完成这个遍历,根本不用手写循环:

-- 完全复用你现有逻辑的写法
getAtIndices myList myIndices = map (\idx -> head (drop idx myList)) myIndices

-- 用内置的!!运算符可以简化,myList !! idx 和 head (drop idx myList) 效果完全一致
getAtIndices' myList myIndices = map (myList !!) myIndices

这个方案的特点:

  • 结果顺序和你传入的myIndices顺序完全一致,比如传[3,1,5],结果就按第3位、第1位、第5位的顺序返回
  • 如果索引列表里有重复值,结果里会对应返回重复的元素
  • 和你原来的单索引写法有一样的问题:传负数、或者索引超出列表长度时会直接抛运行时错误,要更稳妥的话可以自己写个返回Maybe类型的安全索引函数替换!!,自动跳过非法索引即可

基于filter的实现

用filter完全可以实现,只是思路要转个弯:filter是按条件筛选原列表元素,所以得先给原列表的每个元素绑上它对应的位置索引,再把索引在目标集合里的元素筛出来就行:

import qualified Data.Set as Set

getAtIndicesFilter myList myIndices =
  map snd $ filter (\(idx, _) -> idx `Set.member` idxSet) (zip [0..] myList)
  where idxSet = Set.fromList myIndices

这里把索引列表转成Set是为了提升查询效率,要是直接用elem在列表里判断索引是否存在,索引多的时候性能会差很多。
这个方案的特点:

  • 结果顺序和原列表的元素顺序完全一致,和你传入的索引列表顺序无关,哪怕传[3,1,5],结果还是按第1位、第3位、第5位的原列表顺序返回
  • 索引列表里的重复值不会导致结果出现重复元素
  • 天然不存在索引越界问题,超出列表长度的索引会被直接忽略,不会抛错

选型建议

如果你需要严格匹配传入索引的顺序、或者需要支持重复索引取重复值,选第一种map的写法最简洁;如果你只需要拿到所有对应位置的元素、不需要保持索引的输入顺序,选第二种filter写法更稳定,不会因为非法索引崩溃。

内容的提问来源于stack exchange,提问作者halloleo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 07:09:17