Как разбить список на части равного размера в Racket (Схема)?

Пример:
Как преобразовать список:
'(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)

В список списков:
'((0 1 2 3) (4 5 6 7) (8 9 10 11) (12 13 14 15))

На основании ответов, предоставленных до сих пор, я пришел к следующему:

Сначала определите функцию, которая принимает до 'n' элементов от начала списка:

(define (take-up-to n xs)
  (define (iter xs n taken)
    (cond
      [(or (zero? n) (empty? xs)) (reverse taken)]
      [else (iter (cdr xs) (- n 1) (cons (car xs) taken))]))
  (iter xs n '()))

Вторая аналогичная функция для остальной части списка:

(define (drop-up-to n xs)
  (define (iter xs n taken)
    (cond
      [(or (zero? n) (empty? xs)) xs]
      [else (iter (cdr xs) (- n 1) (cons (car xs) taken))]))
  (iter xs n '()))

Это можно было бы сделать как одну функцию, которая возвращает два значения, а Racket имеет функция split-at, которая дает тот же результат, но я сделал это в качестве упражнения.

пс. Правильно ли это использование хвостовой рекурсии?

Тогда разбиение на блоки можно записать так:

(define (split-into-chunks n xs)
  (if (null? xs)
      '()
      (let ((first-chunk (take-up-to n xs))
            (rest-of-list (drop-up-to n xs)))
        (cons first-chunk (split-into-chunks n rest-of-list)))))

pps. Можно ли улучшить его еще больше или он «достаточно хорош»?

5
задан PopMilo 7 January 2012 в 20:15
поделиться