List 消除racket中列表中元素的最后一次出现
我只是想知道,我能不能在racket中创建一个函数来消除列表中最后出现的元素,例如List 消除racket中列表中元素的最后一次出现,list,recursion,scheme,racket,List,Recursion,Scheme,Racket,我只是想知道,我能不能在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,而无需递归调用,也无需使用冗余反向 (defin
>(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,而无需递归调用,也无需使用冗余反向
(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))))
您会注意到拐角处的情况,其中carlst是一个列表。
如果它是一个列表,我们必须检查它是否出现el
重要的是,我们调用该列表上的last without,而不是remove-last-rec。这是因为嵌套列表没有被start调用reverse remove last rec reverse list中的原始reverse反转
如果调用remove last rec,则嵌套列表的顺序将在结果中出错。我建议你试着用一个错误的调用来删除最后一个rec,尝试列出你认为可能失败的列表是非常有益的
如果你找不到,试试这个。
它不会输出您所期望的内容
(last-without '(a (b c a c) b) 'c)
编辑:角落案例需要显式测试,以检查last With nested el是否返回相同的嵌套列表。如果没有,嵌套列表中最后出现的el已被过滤掉,我们不再需要过滤rest中最后出现的el。这里有一个解决方案:
(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元素。试试看
(define (remove-last xs)
(reverse (remove-first (reverse xs) x)))
其中remove first xs x将删除xs中第一个出现的x。在类似last的情况下,如果没有'p'p,您的解决方案将返回p。这对嵌套列表不起作用,是吗?当在remove first过程中遇到嵌套列表时,不会将其反转,因此删除嵌套列表中的第一个而不是最后一个。仅当remove first在下降到子树时调用remove last时,才会执行此操作。但目的是让OP自己先编写remove。