消除球拍中列表中最后一个元素的出现

时间:2015-09-15 22:53:49

标签: list recursion scheme racket

我只是想知道,我可以在球拍中创建一个可以消除列表中最后一个元素的功能,例如,

>(last-without   '(a b  a  (c e) d)    'e)  =  (a b a (c) d)
>(last-without   '(p q  p (r p) q e p r)   'p) = (p q  p (r p) q e r)

也可以通过通过推广内置成员来定义嵌套列表的成员资格测试来完成此操作,该内置成员可用于设置 last-without 递归调用,而不使用冗余反转。

3 个答案:

答案 0 :(得分:1)

(define (last-without list el)
  (define (remove-last-rec lst)
    (cond ((null? lst) '())
          ((equal? (car lst) el) (cdr lst))
          ; Corner case below, if car is a list, we also have to check it for occurences of el
          ((list? (car lst)) (let* ((nested (car lst))
                                    (rest (cdr lst))
                                    (nested-res (last-without nested el)))
                               (if (equal? nested nested-res)
                                   (cons nested-res (remove-last-rec rest)); el did not occur in nested list
                                   (cons nested-res rest)))) ; We did removed it, not remove it from cdr anymore, instead just cons the unchanged cdr.
          (else (cons (car lst) (remove-last-rec (cdr lst))))))

  (reverse ; Reverse filtered list back to original order
   (remove-last-rec 
    (reverse list))))

您会注意到(car lst)是列表的角落情况。 如果是列表,我们必须检查它是否出现el

重要是我们在该列表上调用last-without而不是remove-last-rec。这是因为嵌套列表未被起始调用reverse中的原始(reverse (remove-last-rec (reverse list)))反转。

如果您要调用remove-last-rec,嵌套列表的顺序将在结果中出错。我建议你自己尝试(对remove-last-rec的错误调用),尝试提出你认为可能失败的列表是非常有益的。

如果你找不到,试试这个。 它不会输出您期望的结果。

(last-without '(a (b c a c) b) 'c)

编辑:角落案例需要一个明确的测试来检查(last-without nested el)是否返回相同的嵌套列表。如果没有,嵌套列表elnested的最后一次出现被过滤掉,我们不需要过滤el restvar deferred = new $.Deferred(); deferred.resolve(); deferred.then(function () { try { throw new Error(); } catch (err) { return $.Deferred().reject(); } }).then(function () { console.log('success', arguments); }, function () { console.log('fail', arguments); }); 的最后一次出现了。

答案 1 :(得分:1)

这是一个解决方案:

(define (last-without lst el)
  (define (aux lst)  ; returns two values: removed and result
    (if (null? lst)
        (values #f '())
        (let-values (((removed result) (aux (cdr lst))))
                (if removed
                    (values removed (cons (car lst) result))
                    (cond ((equal? (car lst) el) (values #t result))
                          ((list? (car lst))
                           (let-values (((removed-from-car result-of-car) (aux (car lst))))
                             (values removed-from-car (cons result-of-car result))))
                          (else (values #f (cons (car lst) result))))))))
  (let-values (((removed result) (aux lst)))
    result))

辅助函数执行元素的删除并返回两个值:如果元素已被删除,则为布尔值#t,以及结果列表。因此,在检查列表不为空之后,它将自身应用于列表的其余部分,返回两个值。如果removed#t,则无需执行任何其他操作,并且列表将重建。否则函数必须仍然删除元素,因此它检查它是否等于lst的第一个元素并在这种情况下删除它,否则,如果第一个元素是一个列表,自称在上面。

最后请注意,标题在某种程度上具有误导性:该函数不会从列表中删除最后一个el元素,而是从树中最右边的el元素中删除。

答案 2 :(得分:1)

尝试

(define (remove-last xs)
  (reverse (remove-first (reverse xs) x)))

其中(remove-first xs x)将删除xs中第一次出现的x