Haskell技术问题:根据列表索引重复元素(禁用预定义列表函数)
解决Haskell按索引重复列表元素的问题
首先,咱们来拆解下你当前代码的核心问题:你的test函数没有跟踪每个元素的索引位置,所以没法根据索引值控制重复次数——当前逻辑只是把第一个元素之后的每个元素多复制一次,自然达不到按索引重复的要求。
要实现需求,我们需要一套能携带索引信息的递归逻辑,这里可以用辅助函数来传递当前元素的索引值。具体步骤如下:
1. 自定义元素重复函数
因为题目要求不能用预定义列表函数,我们自己写一个repeatN函数,用来把单个元素重复指定次数:
repeatN :: Int -> a -> [a] repeatN 0 _ = [] repeatN n x = x : repeatN (n-1) x
这个函数的逻辑很直观:重复0次返回空列表;重复n次的话,先放一个目标元素,再递归重复剩下的n-1次。
2. 带索引的主递归逻辑
我们写一个主函数,调用携带索引的辅助函数,初始索引设为1(匹配你例子里第一个元素对应索引1、重复1次的规则):
test :: [a] -> [a] test xs = helper 1 xs where -- 辅助函数:参数是当前元素的索引n,以及剩余待处理的列表 helper _ [] = [] helper n (x:xs) = repeatN n x ++ helper (n+1) xs
逻辑细节解释:
- 当待处理列表为空时,直接返回空列表;
- 处理列表的第一个元素
x时,先用repeatN n x生成重复n次的x序列; - 递归处理剩余列表
xs,同时把索引n加1(下一个元素的索引要递增); - 最后用
++把当前元素的重复序列和后续结果拼接起来。
3. 测试验证
输入你的示例测试用例:
test ['1', '2', '3']
会得到期望的输出:['1', '2', '2', '3', '3', '3']
为什么你的原代码不符合需求?
你的原代码:
test [] = [] test (first:[]) = [first] test (first:second:rest) = first : second : test (second:rest)
每次递归都会把second放到rest的前面,相当于每个元素只会被多复制一次(总共两次),完全没有结合索引来控制重复次数,所以只能实现“每个元素重复两次”的效果,和题目要求的按索引重复逻辑不符。
内容的提问来源于stack exchange,提问作者Pal
相关产品推荐
相关产品推荐

