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

如何将列表拆分为偶数索引元素列表与奇数索引元素列表?

拆分列表为偶数索引与奇数索引元素的方案

你的递归实现已经非常优雅且贴合Haskell的函数式风格了!先帮你拆解下这个方案的逻辑,再补充几种常见的替代实现思路供你参考:

你的现有递归方案解析

你写的这个递归函数逻辑清晰、完全正确:

breakByIndexes [] = ([], [])
breakByIndexes [e] = ([e], [])
breakByIndexes (e:o:xs) = let (es, os) = breakByIndexes xs in (e : es, o : os)
  • 空列表直接返回两个空列表,作为递归的终止条件
  • 单个元素的列表,因为它处于0号偶数索引,所以归入第一个列表,第二个列表为空
  • 当列表有至少两个元素时,把第一个元素(偶数索引)放到结果的第一个列表,第二个元素(奇数索引)放到结果的第二个列表,再递归处理剩余子列表并拼接最终结果

这个实现的时间复杂度是O(n),空间复杂度也是O(n),效率拉满。

其他可选实现思路

如果你好奇有没有不同写法,这里有几种常见的替代方案:

1. 使用foldr折叠实现

借助折叠函数遍历列表,同时跟踪当前元素的索引奇偶性:

breakByIndexes :: [a] -> ([a], [a])
breakByIndexes xs = foldr (\(idx, val) (es, os) -> if even idx then (val:es, os) else (es, val:os)) ([], []) (zip [0..] xs)

先用zip [0..] xs给每个元素附上索引,再通过foldr遍历,根据索引奇偶性把元素分到对应列表中。

2. 使用列表推导式

通过两次列表推导分别提取偶数索引和奇数索引的元素:

breakByIndexes :: [a] -> ([a], [a])
breakByIndexes xs = ( [xs !! i | i <- [0,2..length xs -1]]
                    , [xs !! i | i <- [1,3..length xs -1]] )

注意:(!!)操作符是O(n)时间复杂度,所以这个方案整体时间复杂度为O(n²),更适合短列表场景,长列表下效率不如递归或折叠方案。

3. 使用partition结合索引

给元素添加索引后,用partition拆分再剥离索引:

import Data.Bool (bool)

breakByIndexes :: [a] -> ([a], [a])
breakByIndexes xs = let indexed = zip [0..] xs
                        (evenIdx, oddIdx) = partition (even . fst) indexed
                    in (map snd evenIdx, map snd oddIdx)

partition会将满足“索引为偶数”条件的元素归入第一个列表,剩余的归入第二个,最后通过map snd去掉索引得到结果。

总结

你的原始递归方案其实是最地道的Haskell写法之一,简洁又高效。如果只是满足需求,它完全够用;要是想探索不同的函数式技巧,上面的几种方案可以作为参考。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:27:45