我需要编写一个名为remove-2nd的函数,该函数从项列表中删除给定项的第二个顶级项。这就是我现在拥有的:
(define (remove-2nd item list)
(cond
((null? list) '())
((equal? item (car list))
(cdr list))
(else
(cons (car list) (remove-2nd item (cdr list)))
)))
现在,它只删除第一个引用。(remove-2nd'c'(a b c d c x c((返回(a b d c x c(何时我应该得到(a b c d x c(。
对于空列表和单元素列表,我们只返回列表。否则,我们将查看列表中的第一个项目是否与要删除的项目相同。如果它是我们试图删除的项,那么我们将删除列表其余部分中该元素的下一个出现,如果不是,我们将在列表其余部分重复出现。
(define (remove-2nd item l)
(cond
((null? l) '())
((null? (cdr l)) l)
(else (if (equal? item (car l))
(cons (car l) (remove item (cdr l)))
(cons (car l) (remove-2nd item (cdr l)))))))
在Racket:中使用模式匹配
(define (remove-2nd e l)
(match l
[(or `() `(e)) l]
[(cons f r) (cons f (if (equal? e f) (remove e r) (remove-2nd e r)))]))
一些测试:
(remove-2nd 1 '())
; => '()
(remove-2nd 1 '(1))
; => '(1)
(remove-2nd 1 '(2))
; => '(2)
(remove-2nd 1 '(2 2))
; => '(2 2)
(remove-2nd 1 '(1 1))
; => '(1)
(remove-2nd 1 '(1 2))
; => '(1 2)
(remove-2nd 'c '(a b c d c x c))
; => '(a b c d x c)
一般(尾调用递归(解决方案remove-nth
,然后是特殊情况n = 2
。
(define (remove-nth item l n (test equal?) (acc '()) (counter 1))
(cond
((null? l) (reverse acc))
((test (car l) item) (if (= counter n)
(remove-nth item (cdr l) n test acc (+ counter 1))
(remove-nth item (cdr l) n test (cons (car l) acc) (+ counter 1))))
(else (remove-nth item (cdr l) n test (cons (car l) acc) counter))))
(define (remove-2nd item l (test equal?))
(remove-nth item l 2 test))