首页 > 解决方案 > Haskell - 如何使用递归将列表拆分为 n 个长子部分

问题描述

下面的代码给出了一个基本的想法。我想通过递归将其扩展到列表的其余部分,但使用 where 语法根本无法提供有能力的代码。我试图用@done 命名列表的其余部分,但没有成功。我仍在通过这段代码学习 Haskell,所以我宁愿不使用任何简单的解决方案,如 splitAt 函数等。

splitEv :: Int -> [a] -> [[a]]
splitEv n [] = []
splitEv n (x:xs) = [take n (x:xs)] ++ [(take n(drop n (x:xs)))]

标签: haskell

解决方案


最后一行应该是

 splitEv n xs = [take n xs] ++ (splitEv n (drop n xs))

在等式的后半部分,除了列表的前 n 个元素之外,对列表的其余部分调用 splitEv。这将一直持续到列表为空。

使用@chi 评论编辑
很少有优化是可能的。
在第二行中,n 不是必需的,它可以用 _ 代替。
在第三行:可以用来代替 ++。它更加优化。也可以减少括号。

splitEV  _ [] = []
splitEV n xs = take n xs:(splitEV n $ drop n xs) 

: 和 ++ 之间的区别(在@chepner 评论的帮助下)。
签名:

  (:) :: a -> [a] -> [a]

而 ++ 是

  (++) :: [a] -> [a] -> [a]

: 用于在头部添加单个元素,而 ++ 用于连接两个列表。尽可能使用 : ,因为它更优化。将其视为在链表的开头添加一个元素。您只需要调整头部元素。
这只是为了比喻,在幕后可能会发生更多的事情。


推荐阅读