Haskell新手求助:实现scanD函数完成嵌套列表展开需求
完成scanD函数的解决方案
首先,先确认你的expand函数逻辑是对的——它接收一个形如[值, 重复次数]的列表,返回该值重复对应次数的列表,比如expand [7,3]会生成[7,7,7],完全符合需求👍。
接下来要实现的scanD函数,核心就是遍历嵌套列表中的每一个子列表,对每个子列表调用expand展开,然后把所有展开后的列表拼接在一起。这里用递归的方式就能轻松实现:
main= print(scanD [[7,3],[8,5],[7,2]]) expanding :: Int -> [Int] -> [Int] expanding y (n:ns) | (n>0) = y:expanding y (n-1:ns) | otherwise = [] expand :: [Int] -> [Int] expand (x:xs) = expanding x xs scanD :: [[Int]] -> [Int] scanD [] = [] -- 空的嵌套列表返回空列表,作为递归终止条件 scanD (sub:rest) = expand sub ++ scanD rest -- 展开第一个子列表,拼接剩余子列表的展开结果
逻辑解释
- 空列表情况:当
scanD接收空的嵌套列表时,直接返回空列表,结束递归。 - 非空列表情况:
- 取出第一个子列表
sub,用expand把它展开成重复值的列表; - 递归调用
scanD处理剩下的子列表rest,得到它们的展开结果; - 用
++把这两部分结果拼接起来,就得到了最终的展开列表。
- 取出第一个子列表
测试你的例子,scanD [[7,3],[8,5],[7,2]]会依次处理:
expand [7,3]→[7,7,7]expand [8,5]→[8,8,8,8,8]expand [7,2]→[7,7]
拼接后就是[7,7,7,8,8,8,8,8,7,7],完全符合你的需求。
更简洁的写法
如果你熟悉Haskell的高阶函数,还可以用concatMap来简化scanD的实现,一行就能搞定:
scanD :: [[Int]] -> [Int] scanD = concatMap expand
concatMap会自动遍历列表中的每个元素,应用expand函数,然后把所有结果拼接成一个列表,效果和递归写法完全一致。
内容的提问来源于stack exchange,提问作者Chimoki
相关产品推荐
相关产品推荐

