我想获得一个从原始列表中删除第n个版本的列表。我可以管理以下代码,这是必要的:
(define (list-removeN slist n)
(define outl '())
(for ((i (length slist)))
(when (not (= i n))
(set! outl (cons (list-ref slist i) outl))))
(reverse outl))
这可能与功能相当吗?我试过/ list,但我必须插入#f或在那个位置,删除哪个不理想,因为#f或者也可能出现在列表中的其他位置。
答案 0 :(得分:2)
您可以使用累加器递归执行此操作。像
这样的东西#lang racket
(define (remove-nth lst n)
(let loop ([i 0] [lst lst])
(cond [(= i n) (rest lst)]
[else (cons (first lst) (loop (add1 i) (rest lst)))])))
(remove-nth (list 0 1 2 3 4 5) 3)
(remove-nth (list 0 1 2 3) 3)
(remove-nth (list 0 1 2) 0)
这会产生
'(0 1 2 4 5)
'(0 1 2)
'(1 2)
您可以使用for/list
执行此操作,但由于length
调用,此版本会遍历列表两次。
(define (remove-nth lst n)
(for/list ([i (length lst)]
[elem lst]
#:when (not (= i n)))
elem))
还有split-at
,但这可能不会像创建两个列表并附加它们那样最佳。
(define (remove-nth lst n)
(let-values ([(left right) (split-at lst n)])
(append left (rest right))))
答案 1 :(得分:2)
典型的滚动您自己的递归实现并使用O(n)时间和O(n)空间。
(define (remove-nth lst i)
(let aux ((lst lst) (i i))
(cond ((null? lst) '()) ;; what if (< (length lst) i)
((<= i 0) (cdr lst)) ;; what if (< i 0)
(else (cons (car lst)
(aux (cdr lst) (sub1 i)))))))
使用srfi-1的append-reverse的交互式版本。 O(n)时间和O(1)空间。
(define (remove-nth lst i)
(let aux ((lst lst) (i i) (acc '()))
(cond ((null? lst) (reverse acc)) ;; what if (< (length lst) i)
((<= i 0) (append-reverse acc (cdr lst))) ;; what if (< i 0)
(else (aux (cdr lst) (sub1 i) (cons (car lst) acc))))))