Example:
How to convert list:
‘(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
Into list of lists:
‘((0 1 2 3) (4 5 6 7) (8 9 10 11) (12 13 14 15))
Based on answers provided here so far, this is what I’ve come up with:
First define function to take up to ‘n’ elements from beginning of the list:
(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 '()))
Second is similar function for the rest of list:
(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 '()))
This could have been done as one function that returns two values and Racket has a function ‘split-at’ that produces same result, but I did this as an exercise.
ps. Is this correct use of tail recursion ?
Than split-into-chunks can be written like this:
(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. Can this one be improved even more or is it ‘good enough’ ?
There’s a common utility function in Scheme, in the SRFI-1 library (which Racket offers, but I don’t recall how to import it), called
take, which takes the initialnelements from a list:There is also in the same library a function called
dropwhich removes the initialnelements from a list:You can break down the problem into smaller pieces by using functions like these. So, a first (but incorrect) approximation to solving your problem would be this:
As I noted, however, this solution is suboptimal. Why? Because
(take n xs)gives you an error when the listxshas fewer thannelements; translated to your problem, if the list has a non-nmultiple of elements you get an error. However, you can fix this by writing a pair of functions,take-up-toanddrop-up-tothat work liketakeanddropbut don’t have that problem. So example usage of the functions would look like this:This is as much as I’m going to tell you. I suggest you do these things:
take,drop,take-up-toanddrop-up-to, and use them to write the function you’re trying to implement.EDIT: Here’s simple implementation of
take-up-to:It’s possible to improve on this still some more to use only tail calls (and thus run in constant space). That’s left as yet another exercise.