Como faço para tirar uma fatia de uma lista (A sublist) no esquema?
Pergunta
Dada uma lista, como eu selecionar uma nova lista, que contém uma fatia da lista original (dado offset e número de elementos)?
EDIT:
Boas sugestões até agora. Não há algo especificado em um dos de SRFI? Esta parece ser uma coisa muito fundamental, por isso estou surpreso que eu preciso para implementá-lo em user-terra.
Solução
O código a seguir irá fazer o que quiser:
(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))))
Exemplo:
> (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)
>
Outras dicas
Estranhamente, slice
não é fornecido com SRFI-1 mas você pode torná-lo mais curto usando de SRFI-1 take
e drop
:
(define (slice l offset n)
(take (drop l offset) n))
Eu pensei que uma das extensões que eu usei com Scheme, como a biblioteca PLT Scheme ou Swindle, teria este built-in, mas não parece ser o caso. Não é sequer definido nas novas bibliotecas R6RS.
Você pode tentar esta função:
subseq sequência inicial e final opcional
O Iniciar parâmetro é o seu deslocamento. O final parâmetro pode ser facilmente transformado no número de elementos de agarrar simplesmente adicionando começo + número-of-elementos.
Um pequeno bônus é que subseq funciona em todas as seqüências, o que inclui não só as listas, mas também cordas e vetores.
Edit:. Parece que nem todas as implementações Lisp tem subseq, embora ele vai fazer o trabalho muito bem se tiver
(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 '())))
Aqui está minha implementação do slice
que usa uma chamada cauda adequada
(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)
Tente algo parecido com isto:
(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)))
'()))))