如何实现不丢失头部的Haskell列表对半拆分函数?
问题分析与解决
你的代码在处理长度大于1的列表时,直接对xs(原列表去掉头部后的剩余部分)执行splitAt,但计算的half是xs长度的一半,相当于把原列表的第一个元素完全排除在拆分逻辑外,自然会丢失头部元素。
下面是两种修正方案:
方案一:简洁版实现
直接基于整个列表的长度计算拆分点,同时简化分支逻辑:
halve :: [a] -> ([a],[a]) halve [] = ([],[]) halve [x] = ([x],[]) halve xs = splitAt (length xs `div` 2) xs
调用halve [1,2,3,4]时,length xs为4,div 2得到拆分点2,splitAt 2 [1,2,3,4]会直接返回([1,2],[3,4]),完全符合你的需求。
方案二:保留原分支结构的实现
如果想保留原有的(x:xs)分支写法,可以将头部元素x拼到拆分后的第一个列表中,同时调整拆分点:
halve :: [a] -> ([a],[a]) halve [] = ([],[]) halve [x] = ([x],[]) halve (x:xs) = (x : firstPart, secondPart) where totalLength = 1 + length xs half = totalLength `div` 2 (firstPart, secondPart) = splitAt (half - 1) xs
这里先计算原列表的总长度,拆分点half取总长度的一半,再对xs拆分half-1个元素,最后把头部x加到第一个拆分结果的前面,同样能得到正确输出。
内容的提问来源于stack exchange,提问作者JasperBlink
相关产品推荐
相关产品推荐

