Reputation: 611
I'm trying to remove both the first and the last elements of a list in Racket. Is there some other way of doing this instead of:
(cdr (reverse (cdr (reverse my-list))))
Upvotes: 2
Views: 2374
Reputation: 236140
Here's one way to do it, using Racket's built-in procedures:
(define my-list '(1 2 3 4 5 6 7 8 9 10))
(drop-right (rest my-list) 1)
=> '(2 3 4 5 6 7 8 9)
Note: we can use cdr
instead of rest
, but rest
is more idiomatic in Racket. For a more general solution:
; remove `left` number of elements elements from the left side
; and `right` number of elements from the right side of the list
(define (trim lst left right)
(drop-right (drop lst left) right))
(trim my-list 1 1)
=> '(2 3 4 5 6 7 8 9)
(trim my-list 2 4)
=> '(3 4 5 6)
Upvotes: 2
Reputation: 48775
The method you present uses some memory since it cons n cells that are thrown away in the process when you again reverse it. However Óscars solution also cons n cells so it may help clarity it certainly won't do it faster.
On a 5 million element list it takes about 1,6 seconds when compiled (on my machine) and that is mostly gc time. If you find you have performance problems and you are writing scheme (not racket language) you can get it 4 times faster (400ms) by doing one pass manual tail recursive modulo cons:
#!r6rs
(import (rnrs)
(rnrs mutable-pairs))
(define (middle lst)
(define head (list 1))
(let loop ((tail head) (lst (cdr lst)))
(if (and (pair? lst) (pair? (cdr lst)))
(begin
(set-cdr! tail (list (car lst)))
(loop (cdr tail) (cdr lst)))
(cdr head))))
As you can see it's quite ugly so you must really want more performance to replace 2 reverses and 2 cdrs with this.
Upvotes: 0