如何解决获取惰性列表的第一个元素的问题?
Posted
技术标签:
【中文标题】如何解决获取惰性列表的第一个元素的问题?【英文标题】:How to fix problem taking first element of lazy list? 【发布时间】:2019-05-04 12:44:12 【问题描述】:我想创建一个函数,该函数采用 int
的惰性列表并随着元素数量的增加返回惰性列表,每个元素 x
必须重复 x
次。例如,我将像常规一样编写惰性列表,为了提高可读性,我将函数 [1; 2; 3],返回[1; 2; 2; 3; 3; 3]。
我写了一些代码,必须这样做:
type 'a lazyList = LNil | LCons of 'a * (unit -> 'a lazyList);;
let lhd = function
| LNil -> failwith "lhd"
| LCons (x, _) -> x
;;
let ltl = function
| LNil -> failwith "ltl"
| LCons (_, xf) -> xf()
;;
let increase llist =
let rec increaseHelper (count, lList) = match (count, lList) with
| (0, LCons(_, xf)) -> increaseHelper((lhd (ltl llist)), (xf()))
| (_, LCons(x, _)) -> LCons(x, function() -> increaseHelper(count - 1, lList))
| (_, LNil) -> LNil
in increaseHelper(lhd llist, llist)
;;
(* ltake函数返回n个常规列表中的惰性元素*)
let rec ltake = function
| (0, _) -> []
| (_, LNil) -> []
| (n, LCons(x, xf)) -> x :: ltake(n - 1, xf())
;;
ltake (20,increase (LCons(4, function() -> LCons(3, function() -> LCons(1, function() -> LCons(4, function() -> LNil))))));;
这个测试返回: - : int list = [4; 4; 4; 4; 3; 3; 3; 1个; 1个; 1个; 4; 4; 4]
所以主要问题是增加函数对于惰性列表的前两个元素工作正常,但是在 3 - 无穷大元素它保存语句从 2 个元素,重复元素多少次
【问题讨论】:
【参考方案1】:首先,您的代码无法编译。我想你写的地方,
| (0, LCons(_, xf)) -> increaseHelper((lhd xf), (xf()))
你的意思是写
| (0, LCons(_, xf)) -> increaseHelper((lhd (xf())), xf())
但是这会失败,因为当 xf()
可能是 LNil
时,您调用了 lhd (xf())
。实际上,如果列表为空,您一开始就会失败。
in increaseHelper(lhd llist, llist)
您可以尝试根据您最初的想法修复您的代码,但复杂的部分原因是当您达到 0 时,要重置计数器,您需要查看尾部的头部(如果它不为零)。
所以这是另一个想法。为什么增加而不是减少计数器?从 0 开始计数器,并增加它直到计数器匹配头部。它可能看起来没有太大不同,但它更容易,因为重置计数器不需要您查看列表。
let rec increaseHelper(n,llist) = match llist with
| LNil -> LNil
| LCons(x,xf) -> if n == x
then increaseHelper(0, xf())
else LCons(x, function() -> increaseHelper(n+1, llist))
并从 0 开始进行初始调用,
in increaseHelper(0, llist)
【讨论】:
非常感谢您的帮助。我只有一个问题,是否可以让这个函数对零以下的数字起作用? 我猜是这样,但是您需要说明它应该如何处理负数x
(将元素复制负数次是什么意思?)。如果您希望将负数 x
复制 0 次(即像 0 一样过滤掉),那么只需将 if n== x
更改为 if n>=x
即可。以上是关于如何解决获取惰性列表的第一个元素的问题?的主要内容,如果未能解决你的问题,请参考以下文章