Group List by Number
The following functions will group items in a supplied list into sublists of a given length (or less than the given length if the number of items in the original list is not evenly divisible by the group size).
Both functions will return a list of lists, in which the number of items within each sublist is at most the length specified by the second function argument.
Such functions are particularly useful when converting the 1-dimensional continuous list of x, y, & z coordinate values as returned by the ActiveX Coordinates property for a 2D or 3D polyline into a list of 2D or 3D points.
Groups of Maximum Length
Function Syntax | (LM:group<n <l> <n>) |
Current Version | 1.0 |
Donate |
Arguments | ||
---|---|---|
Symbol | Type | Description |
l | List | List to process |
n | Integer | Maximum number of items in each sublist (n > 0) |
Returns | ||
Type | Description | |
List | A list of lists, each of maximum length 'n', grouping elements of the original list |
Function Description
This function will group items of a supplied list into lists of a maximum given length, that is, if the supplied list contains a number of items which is not evenly divisible by the group size, the last sublist in the list returned by the function will contain fewer items.
Recursive Version
;; Group by Number - Lee Mac ;; Groups a list 'l' into a list of lists, each of max length 'n' (defun LM:group<n ( l n ) (if l (LM:group<n-sub (cons nil l) n n)) ) (defun LM:group<n-sub ( l m n ) (if (and (cdr l) (< 0 n)) (LM:group<n-sub (cons (cons (cadr l) (car l)) (cddr l)) m (1- n)) (cons (reverse (car l)) (LM:group<n (cdr l) m)) ) )
Iterative Version
;; Group by Number - Lee Mac ;; Groups a list 'l' into a list of lists, each of max length 'n' (defun LM:group<n ( l n / a b m ) (while l (setq m n) (while (and l (< 0 m)) (setq a (cons (car l) a) l (cdr l) m (1- m) ) ) (setq b (cons (reverse a) b) a nil ) ) (reverse b) )
Example Function Calls
As shown by the last example, if the supplied list does not divide evenly into lists of the specified length, the last sublist will contain fewer items.
_$ (LM:group<n '("A" "B" "C" "D" "E" "F") 2) (("A" "B") ("C" "D") ("E" "F"))
_$ (LM:group<n '(0 1 2 3 4 5) 3) ((0 1 2) (3 4 5))
_$ (LM:group<n '(0 1 2 3 4 5) 4) ((0 1 2 3) (4 5))
Groups of Fixed Length
Function Syntax | (LM:group-n <l> <n>) |
Current Version | 1.0 |
Donate |
Arguments | ||
---|---|---|
Symbol | Type | Description |
l | List | List to process |
n | Integer | Number of elements by which to group the list (n > 0) |
Returns | ||
Type | Description | |
List | A list of lists, each of length 'n', grouping elements of the original list |
Function Description
This function will group elements of a supplied list into lists of a fixed length, that is, if the supplied list contains a number of items which is not evenly divisible by the group size, the last sublist in the list returned by the function will contain nil values to ensure all sublists are of the same fixed length/size.
Recursive Version
;; Group by Number - Lee Mac ;; Groups a list 'l' into a list of lists, each of length 'n' (defun LM:group-n ( l n / r ) (if l (cons (reverse (repeat n (setq r (cons (car l) r) l (cdr l)) r)) (LM:group-n l n) ) ) )
Iterative Version
;; Group by Number - Lee Mac ;; Groups a list 'l' into a list of lists, each of length 'n' (defun LM:group-n ( l n / a b ) (while l (repeat n (setq a (cons (car l) a) l (cdr l) ) ) (setq b (cons (reverse a) b) a nil ) ) (reverse b) )
Example Function Calls
As shown by the last example, if the supplied list does not divide evenly into lists of the specified length, nil values will occupy the remainder list elements.
_$ (LM:group-n '("A" "B" "C" "D" "E" "F") 2) (("A" "B") ("C" "D") ("E" "F"))
_$ (LM:group-n '(0 1 2 3 4 5) 3) ((0 1 2) (3 4 5))
_$ (LM:group-n '(0 1 2 3 4 5) 4) ((0 1 2 3) (4 5 nil nil))
Example Program
The following example program demonstrates how this function may be used to group the 1-dimensional list of coordinate values returned by the ActiveX Coordinates property into a list of 2D or 3D points representing the vertices of a selected 2D or 3D polyline:
(defun c:getvertices ( / obj sel ) (if (setq sel (ssget "_+.:E:S" '((0 . "*POLYLINE")))) (mapcar 'print (LM:group-n (vlax-get (setq obj (vlax-ename->vla-object (ssname sel 0))) 'coordinates) (if (= "AcDbPolyline" (vla-get-objectname obj)) 2 3) ) ) ) (princ) ) (vl-load-com) (princ)