如何解决获取惰性列表的第一个元素的问题?

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 即可。

以上是关于如何解决获取惰性列表的第一个元素的问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取 List 或 Set 的第一个元素? [复制]

如何从 Erlang 中的对列表中获取元素

用el标签如何获取列表中的第一个元素?

获取列表的第一个元素

如何实现固定长度的Redis列表?

如何获取列表元素的总和? [关闭]