首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >删除!R5RS函数

删除!R5RS函数
EN

Stack Overflow用户
提问于 2017-03-14 22:31:51
回答 2查看 210关注 0票数 1

我正在尝试编写一个delete!函数,它会改变一个列表并从它中移除一个指定的值。这是我到目前为止掌握的密码。

代码语言:javascript
复制
(define (extend! l . xs)
  (if (null? (cdr l))
      (set-cdr! l xs)
      (apply extend! (cdr l) xs)))

(define (delete! lis y)
  (define returnLis '())
  (for-each (lambda(x) (if(not(eq? x y))
                          (extend! returnLis x))) lis)
  returnLis)

我遇到的问题是,我试图添加到一个空的列表,这是不能做的计划。

预期结果:

(删去'(1 2 3 4 5) 3) => (1 2 4 5)

EN

回答 2

Stack Overflow用户

发布于 2017-03-15 00:55:32

您的extend函数实际上会在一个新的对中生成每个元素的副本,但是由于初始值是'(),所以不能是set-cdr!。突变的全部意义在于,旧变量将继续指向已更改的数据,而复制则不能做到这一点。

你得看看那对。你想要删除3

代码语言:javascript
复制
[1,-]->[2,-]->[3,-]->[4,-]->[5,-]->()

因此,当您找到3时,您需要更改包含2的对的cdr,并将包含3s cdr的对按如下方式排列:

代码语言:javascript
复制
[1,-]->[2,-]->[4,-]->[5,-]->()

就像这样:

代码语言:javascript
复制
(define (delete lst e)
  (if (and (not (null? lst)) (not (null? (cdr lst))))
      (if (equal? (cadr lst) e)
          (set-cdr! lst (cddr lst))
          (delete (cdr lst) e))
      'undefined))

(define test (list 1 2 3 4 5)) 
(delete lst 3)
lst ; ==> (1 2 4 5)

注意,我使用的是list,因为这里不能使用引用的文字,因为不允许更改常量数据(如'(1 2 3 4 5) )。结果将是未定义的,否则会发出错误信号。

如果问题中的元素是第一个元素,它将无法工作。这是因为变量指向第一对,这只会成对地改变指针,而不是绑定。一个可以首先切换两个元素,然后删除第二个元素,但是如果您有一个元素列表,那么您仍然被卡住了。可变队列的方案实现通常有一个头,由一个不被认为是删除第一个元素的列表中的虚拟元素组成。

票数 1
EN

Stack Overflow用户

发布于 2017-03-15 10:42:03

你所需要的只是一种前哨技术

代码语言:javascript
复制
(define (delete! lis y)
  (define returnLis (list 1))
  (for-each (lambda(x) (if(not(eq? x y))
                          (extend! returnLis x))) lis)
  (cdr returnLis))

不是所有的..。因为这是一种二次算法。它从顶部重新搜索returnLis,同时使用extend!添加每个新元素。最好只维护最后一个cell并更新它。

代码语言:javascript
复制
(define (delete! lis y)
  (define returnLis (list 1))
  (define last-cell returnLis)
  (for-each (lambda(x) (cond ((not(eq? x y))
                          ; (extend! last-cell x)
                          (set-cdr! last-cell (list x))
                          (set! last-cell (cdr last-cell)))))
            lis)
  (cdr returnLis))

但是,作为@Sylwester points out,使用这种方法,您不应该在名称中使用感叹号,因为这将返回一个新建的列表,而不是修改参数的结构。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42797803

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档