Given a list, how would I select a new list, containing a slice of the original list (Given offset and number of elements) ?
Good suggestions so far. I
Strangely, slice
is not provided with SRFI-1 but you can make it shorter by using SRFI-1's take and drop:
(define (slice l offset n)
(take (drop l offset) n))
I thought that one of the extensions I've used with Scheme, like the PLT Scheme library or Swindle, would have this built-in, but it doesn't seem to be the case. It's not even defined in the new R6RS libraries.
Try something like this:
(define (slice l offset length)
(if (null? l)
l
(if (> offset 0)
(slice (cdr l) (- offset 1) length)
(if (> length 0)
(cons (car l) (slice (cdr l) 0 (- length 1)))
'()))))
The following code will do what you want:
(define get-n-items
(lambda (lst num)
(if (> num 0)
(cons (car lst) (get-n-items (cdr lst) (- num 1)))
'()))) ;'
(define slice
(lambda (lst start count)
(if (> start 1)
(slice (cdr lst) (- start 1) count)
(get-n-items lst count))))
Example:
> (define l '(2 3 4 5 6 7 8 9)) ;'
()
> l
(2 3 4 5 6 7 8 9)
> (slice l 2 4)
(3 4 5 6)
>
(define (sublist list start number)
(cond ((> start 0) (sublist (cdr list) (- start 1) number))
((> number 0) (cons (car list)
(sublist (cdr list) 0 (- number 1))))
(else '())))
You can try this function:
subseq sequence start &optional end
The start parameter is your offset. The end parameter can be easily turned into the number of elements to grab by simply adding start + number-of-elements.
A small bonus is that subseq works on all sequences, this includes not only lists but also string and vectors.
Edit: It seems that not all lisp implementations have subseq, though it will do the job just fine if you have it.
Here's my implementation of slice
that uses a proper tail call
(define (slice a b xs (ys null))
(cond ((> a 0) (slice (- a 1) b (cdr xs) ys))
((> b 0) (slice a (- b 1) (cdr xs) (cons (car xs) ys)))
(else (reverse ys))))
(slice 0 3 '(A B C D E F G)) ;=> '(A B C)
(slice 2 4 '(A B C D E F G)) ;=> '(C D E F)