Как мне взять фрагмент списка (подсписка) в scheme?
Вопрос
Учитывая список, как бы я выбрал новый список, содержащий фрагмент исходного списка (с учетом смещения и количества элементов)?
Редактировать:
Пока что хорошие предложения.Разве в одном из SRFI что-то не указано?Это кажется очень фундаментальной вещью, поэтому я удивлен, что мне нужно реализовать это на территории пользователя.
Решение
Следующий код будет делать то, что вы хотите:
(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))))
Пример:
> (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)
>
Другие советы
Странно, slice
не обеспечен SRFI-1 но вы можете сделать его короче, используя SRFI-1 take
и drop
:
(define (slice l offset n)
(take (drop l offset) n))
Я думал, что одно из расширений, которые я использовал со Scheme, например PLT Scheme library или Swindle, будет иметь это встроенное, но, похоже, это не так.Это даже не определено в новых библиотеках R6RS.
Вы можете попробовать эту функцию:
последующий этап начало последовательности и необязательный конец
Тот Самый начать параметр - это ваше смещение.Тот Самый конец параметр можно легко преобразовать в количество элементов для захвата, просто добавив start + number-of-elements .
Небольшой бонус заключается в том, что последующий этап работает со всеми последовательностями, включая не только списки, но также строки и векторы.
Редактировать:Похоже, что не все реализации lisp имеют subseq , хотя он отлично справится с этой задачей, если у вас он есть.
(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 '())))
Вот моя реализация slice
это использует правильный хвостовой вызов
(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)
Попробуйте что-то вроде этого:
(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)))
'()))))