return range of list in scheme
in scheme,
list-ref returns only one element.
but I want to do like
(my-list-operation 0 4 '(1 2 3 4 5 6 7 8 9开发者_JAVA百科 10 11 12))
=> '(1 2 3 4)
could somebody tell me how to do this?
I believe in using existing quality libraries where available. So, this answer uses SRFI 1 (if you're using Racket, load it using (require srfi/1)
):
(define (list-range lst start end)
(take (drop lst start) (- end start)))
Example:
(list-range (iota 12 1) 0 4) ; => (1 2 3 4)
(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))))
get-n-items
is a helper, which appends n items together. slice
takes a list, offset and count and again loops until it finds the start index--then returns n items from there.
(From How do I take a slice of a list (A sublist) in scheme?)
(define my-list-operation
(lambda (start end lst)
(cond ((= 0 end) '())
((= 0 start) (cons (car lst) (my-list-operation 0 (- end 1) (cdr lst))))
(else
(my-list-operation (- start 1) (- end 1) (cdr lst))))))
That should do it.
A better solution is:
(define (slice lst start [end #f])
(let ([lst0 (drop lst start)])
(take lst0 (or end (length lst0)))))
Since that will pass the following tests:
(require rackunit)
(test-case "slice list"
(check-equal? (slice '(1 2 3 4) 1 1) '(2))
(check-equal? (slice '(1 2 3 4) 0 1) '(1))
(check-equal? (slice '(1 2 3 4) 0 2) '(1 2))
(check-equal? (slice '(1 2 3 4) 0) '(1 2 3 4))
(check-equal? (slice '(1 2 3 4) 1 2) '(2 3))
(check-equal? (slice '(1 2 3 4) 1) '(2 3 4)))
Chris' solution doesn't cover all of these scenarios.
精彩评论