消除球拍列表中元素的最后一次出现
eliminate the last occurrence of an element in a list in 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 递归调用,而不使用冗余反转。
(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 (remove-last-rec (reverse list)))
中,嵌套列表未被原始 reverse
反转。
如果您调用 remove-last-rec
,结果中嵌套列表的顺序将是错误的。我建议您自己尝试(错误地调用 remove-last-rec
),尝试列出您认为可能会失败的列表非常有启发性。
如果找不到,试试这个。
它不会输出你所期望的。
(last-without '(a (b c a c) b) 'c)
EDIT :极端情况需要显式测试以检查 (last-without nested el)
returns 是否为相同的嵌套列表。如果不是,则嵌套列表 nested
中最后一次出现的 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))
辅助函数执行元素的删除和 returns 两个值:一个布尔值,如果元素已被删除,则为 #t
,以及结果列表。因此,在检查列表不为空后,它将自身应用于列表的其余部分,返回两个值。如果 removed
是 #t
,则不必执行任何其他操作,并且会重建列表。否则函数 必须 仍然删除元素,因此它检查它是否等于 lst
的第一个元素并在这种情况下删除它,否则,如果第一个元素是一个列表,在上面自称。
最后请注意,标题在某种程度上具有误导性:该函数不会删除列表中的最后一个 el
元素,而是删除树中最右边的 el
元素。
尝试
(define (remove-last xs)
(reverse (remove-first (reverse xs) x)))
其中 (remove-first xs x)
将删除 xs 中第一次出现的 x
。
我只是想知道,我可以在球拍中创建一个函数来消除列表中最后一次出现的元素,例如,
>(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 递归调用,而不使用冗余反转。
(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 (remove-last-rec (reverse list)))
中,嵌套列表未被原始 reverse
反转。
如果您调用 remove-last-rec
,结果中嵌套列表的顺序将是错误的。我建议您自己尝试(错误地调用 remove-last-rec
),尝试列出您认为可能会失败的列表非常有启发性。
如果找不到,试试这个。 它不会输出你所期望的。
(last-without '(a (b c a c) b) 'c)
EDIT :极端情况需要显式测试以检查 (last-without nested el)
returns 是否为相同的嵌套列表。如果不是,则嵌套列表 nested
中最后一次出现的 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))
辅助函数执行元素的删除和 returns 两个值:一个布尔值,如果元素已被删除,则为 #t
,以及结果列表。因此,在检查列表不为空后,它将自身应用于列表的其余部分,返回两个值。如果 removed
是 #t
,则不必执行任何其他操作,并且会重建列表。否则函数 必须 仍然删除元素,因此它检查它是否等于 lst
的第一个元素并在这种情况下删除它,否则,如果第一个元素是一个列表,在上面自称。
最后请注意,标题在某种程度上具有误导性:该函数不会删除列表中的最后一个 el
元素,而是删除树中最右边的 el
元素。
尝试
(define (remove-last xs)
(reverse (remove-first (reverse xs) x)))
其中 (remove-first xs x)
将删除 xs 中第一次出现的 x
。