i am trying to group nubers together whichever consecutive
for example : original list '(1 2 3 6 9 10 11 44 55 56 77) in a list
outpot list '((1 2 3)(6)(9 10 11)(44)(55 56)(77))
seems to be simple, but have been strugglig for a day or so...
any help will be gratly appreciated
TIA
Solved! Go to Solution.
Solved by Kent1Cooper. Go to Solution.
@markruys2 wrote:i am trying to group nubers together whichever consecutive
for example : original list '(1 2 3 6 9 10 11 44 55 56 77) in a list
outpot list '((1 2 3)(6)(9 10 11)(44)(55 56)(77))
....
This seems to do that:
(defun CGI (numlist / sublist lastint cumlist); = Consecutively-Grouped Integers
(setq sublist (list (setq lastint (car numlist)))); start first sublist with first integer
(foreach int (cdr numlist)
(if (= int (1+ lastint)); consecutive from previous?
(setq sublist (append sublist (list int))); then -- add it to consecutive group
(setq ; else
cumlist (append cumlist (list sublist)); add so-far group to cumulative list
sublist (list int); start new sublist
); setq
); if
(setq lastint int)
); foreach
(setq cumlist (append cumlist (list sublist))); add last group
); defun
Usage:
Command: (cgi '(1 2 3 6 9 10 11 44 55 56 77))
returns
((1 2 3) (6) (9 10 11) (44) (55 56) (77))
@markruys2 wrote:kent,
thanks for the code, compact and simple
have a nice thankgiving
m
My pleasure. It also occurs to me that it would be easy to have the routine sort the initial list into order, if it may not always be already, just in case.
Dang! I was too slow.
The following will sort *and* not drop duplicate numbers (like vl-sort does).
(defun gl (lst / sl li ml) ;;; quick number grouping ;;; by me ;;; requires (std-%insertion-sort) ;;; by Serge Pashkov ;;; ;;; usage example: (gl '(1 3 4 6 7 8 9 1 4 67)) => ((1 1) (3 4 4) (6 7 8 9) (67)) ;;; (setq sl (list (nth 0 (std-%insertion-sort lst '<))) ml ()) (foreach li (cdr (std-%insertion-sort lst '<)) (if (or (member li sl) (= li (1- (last (std-%insertion-sort sl '<)))) (= li (1+ (last (std-%insertion-sort sl '<))))) (setq sl (std-%insertion-sort (cons li sl) '<)) (setq ml (cons sl ml) sl (list li) ) ) ) (setq ml (reverse (cons sl ml))) ) (defun std-%insertion-sort (lst cmp / M N O cO) ;;; --Part of STDLSP.LSP By: Reini Urban ;;; stable insertion sort, fast for already ordered and short lists ;;; very slow for reversed or random lists O(n^2) ;;; by Serge Pashkov (setq O (reverse lst) M nil N (list (car O))) (while (setq O (cdr O)) (setq cO (car O)) (while (and N (apply cmp (list (car N) cO))) (setq M (cons (car N) M) N (cdr N))) (setq N (cons cO N)) (while M (setq N (cons (car M) N) M (cdr M)))) N)
@Anonymous wrote:....
The following will sort *and* not drop duplicate numbers (like vl-sort does).
....
Interesting idea, if duplicates are a possibility. A more concise way than std-%insertion-sort to sort a list of numerical values and not drop duplicate numbers:
;; SKD = Sort, Keep Duplicates [unlike vl-sort, which eliminates them]
;; for a list of numerical values
(defun SKD (numlist oper / sortlist)
(foreach x (vl-sort numlist oper)
(setq sortlist (append sortlist (vl-remove-if-not '(lambda (y) (= y x)) numlist)))
); foreach
); defun
Usage:
Command: (skd '(1 3 4 6 7 8 9 1 4 67) '<)
returns
(1 1 3 4 4 6 7 8 9 67)
Incorporating that approach into my earlier CGI function:
(defun CGI (numlist / sortlist sublist lastint cumlist); = Consecutively-Grouped Integers
(vl-load-com); [if needed]
(foreach x (vl-sort numlist '<)
(setq sortlist (append sortlist (vl-remove-if-not '(lambda (y) (= y x)) numlist)))
); foreach
(setq sublist (list (setq lastint (car sortlist)))); start first sublist with first integer
(foreach int (cdr sortlist)
(if (or (= int lastint) (= int (1+ lastint))); equal to or consecutive from previous?
(setq sublist (append sublist (list int))); then -- add it to consecutive group
(setq ; else
cumlist (append cumlist (list sublist)); add so-far group to cumulative list
sublist (list int); start new sublist
); setq
); if
(setq lastint int)
); foreach
(setq cumlist (append cumlist (list sublist))); add last group
); defun
Usage:
Command: (cgi '(1 3 4 6 7 8 9 1 4 67))
returns
((1 1) (3 4 4) (6 7 8 9) (67))
@markruys2 wrote:i am trying to group nubers together whichever consecutive
for example : original list '(1 2 3 6 9 10 11 44 55 56 77) in a list
outpot list '((1 2 3)(6)(9 10 11)(44)(55 56)(77))
seems to be simple, but have been strugglig for a day or so...
any help will be gratly appreciated
TIA
Recursion
(Defun groupbycon (n ls ls_) (setq s (apply 'min ls) ls_ (cons s ls_) ls (vl-remove s ls) ) (While (member (Setq s (1+ s)) ls) (setq ls_ (cons s ls_) ls (vl-remove s ls) ) ) (if ls (groupbycon (setq n (cons (reverse ls_) n)) ls nil) (reverse (cons ls_ n)) ) )
(groupbycon nil '(1 2 3 6 9 10 11 44 55 56 77) nil)
(groupbycon nil '(56 1 2 10 11 3 55 6 9 44 77) nil)
((1 2 3) (6) (9 10 11) (44) (55 56) (77))
HTH
Nice one pBe
Here is mine, for non-duplicates list
(defun group_consecutive (l / r) (setq r (list (list (apply 'max l)))) (foreach x (cdr (vl-sort l '>)) (if (= x (1- (caar r))) (setq r (cons (cons x (car r)) (cdr r))) (setq r (cons (list x) r)) ) ) )
@phanaem wrote:Nice one pBe
Here is mine, for non-duplicates list
Clever using MAX and sort phanaem , i like your code
Iteration version of the code using max
(Defun groupbycon (ls / n) (setq s (apply 'max ls)) (While ls (while (member s ls) (setq ls_ (cons s ls_) ls (vl-remove s ls) s (1- s) ) ) (setq n (cons ls_ n) ls_ nil s (apply 'max ls) ) ) n )