haskell - 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)))]
解决方案
最后一行应该是
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]
: 用于在头部添加单个元素,而 ++ 用于连接两个列表。尽可能使用 : ,因为它更优化。将其视为在链表的开头添加一个元素。您只需要调整头部元素。
这只是为了比喻,在幕后可能会发生更多的事情。
推荐阅读
- javascript - MM:SS 格式的默认时间 - Django
- android - 为什么我无法更改 Android 虚拟设备配置中的“仿真性能:图形”设置?
- entity-framework - 如何使用 EF FromSql 编写子句?
- javascript - 如何在java脚本中获取字符串的一部分
- php - 为什么这个 preg_replace 调用返回 NULL?
- javascript - 如何使用 createJS 加载 spritesheet 并运行动画
- python - 使用elementtree和python根据xml上的标签名称替换属性
- bash - 在大文件中用天替换日期
- c# - 如何在 MongoDB C# 中检索更新文档的所有 _id?
- jquery - 使用jquery根据值从数组中获取兄弟值