Many a time you need a list of coordinates, but when working with ActiveX mostly you get a flat array of numbers. Say with a polyline's Coordinates property.
So here I'm attempting a quick-fix to change a list like (X Y X Y X Y ...) into ((X Y) (X Y) (X Y)).
First idea:(defun list-group (lst n / res item)
(while lst
(setq item nil)
(repeat n (setq item (cons (car lst) item) lst (cdr lst)))
(setq res (cons (reverse item) res)))
(reverse res))
Some sample code:_$ (list-group '(1 2 3 4 5 6 7 8 9) 3)
((1 2 3) (4 5 6) (7 8 9))
_$ (list-group '(1 2 3 4 5 6 7 8 9 10) 3)
((1 2 3) (4 5 6) (7 8 9) (10 nil nil))
Clearly if the length of the list is not divisible by the group-by number, you're going to get those nils at the end.
I'm trying to steer clear of nth, since it's rather less efficient than most other methods. Otherwise a simple double increment integer index would have been the most straight-forward principle. Something like this:(defun list-group-i (lst n / item res i j)
(setq i (length lst))
(while (>= (setq i (1- i)) 0)
(setq j n item nil)
(while (>= (setq j (1- j)) 0)
(setq item (cons (nth (+ i j) lst) item)))
(setq res (cons item res) i (- i n -1)))
res)
And yes I have thought of making that 1st one only use one reverse on the main list and then work backwards. Though then what should happen to the case where the list length is not divisible by the grouping count? Perhaps this:(defun list-group1 (lst n / res item)
(setq lst (reverse lst))
(repeat (- n (rem (length lst) n)) (setq lst (cons nil lst)))
(while lst
(setq item nil)
(repeat n (setq item (cons (car lst) item) lst (cdr lst)))
(setq res (cons item res)))
res)
Results thus far on a list of 5000 length:Benchmarking ..........Elapsed milliseconds / relative speed for 128 iteration(s):
(LIST-GROUP1 LST 5)......1030 / 6.53 <fastest>
(LIST-GROUP LST 5).......1061 / 6.34
(LIST-GROUP-I LST 5).....6723 / 1 <slowest>
Clearly the indexed version is way slower than the others. Anyone have any other ideas?