handasa Posted June 11, 2017 Posted June 11, 2017 Greetings everyone i have a list that consist of a sublists each sublist holds an entity name in the drawing "itm" where itm= (setq itm (ssname i ss1)) and distance say the sublist will looks like something like this: ( () (x1) ) so how to sort a larger list contains multiple sublists by entityname first then sorts the list again with the distance (x1 , x2 , ....) so that the last list will look like this ( () (x1) ) ( () (x2) ) ( () (x3) ) ( () (x4) ) ( () (x5) ) ( () (x6) ) thanks Quote
marko_ribar Posted June 11, 2017 Posted June 11, 2017 (edited) itm=(setq itm (ssname ss1 i)) (defun _sort_byenames_bydists ( lst / l a g gg r ) (setq l (vl-sort lst (function (lambda ( a b ) (< (vl-prin1-to-string (caar a)) (vl-prin1-to-string (caar b))))))) (while (setq a (car l)) (setq l (cdr l)) (if (null g) (setq g (cons a g)) ) (if (eq (caar a) (caaar l)) (setq g (cons (car l) g)) (setq gg (cons g gg) g nil) ) ) (foreach g gg (setq r (cons (vl-sort g (function (lambda ( a b ) (< (caadr a) (caadr b))))) r)) ) (apply (function append) r) ) M.R. Edited June 11, 2017 by marko_ribar Quote
Lee Mac Posted June 11, 2017 Posted June 11, 2017 I would suggest: (defun mysort ( l ) (vl-sort l '(lambda ( a b ) (if (eq (caar a) (caar b)) (< (caadr a) (caadr b)) (< (vl-prin1-to-string (caar a)) (vl-prin1-to-string (caar b))) ) ) ) ) However, your list appears to be nested an extra level unnecessarily - why not: ( (<Entity name: name1> x1) (<Entity name: name1> x2) (<Entity name: name1> x3) (<Entity name: name2> x4) (<Entity name: name2> x5) (<Entity name: name2> x6) ) Quote
marko_ribar Posted June 11, 2017 Posted June 11, 2017 @Lee, both codes may fail if list contains exactly equal elements... This are revisions... (defun _s_b_b ( lst / l a g gg r ) (setq l (mapcar (function (lambda ( x ) (nth x lst))) (vl-sort-i lst (function (lambda ( a b ) (< (vl-prin1-to-string (caar a)) (vl-prin1-to-string (caar b)))))))) (while (setq a (car l)) (setq l (cdr l)) (if (null g) (setq g (cons a g)) ) (if (eq (caar a) (caaar l)) (setq g (cons (car l) g)) (setq gg (cons g gg) g nil) ) ) (foreach g gg (setq r (cons (mapcar (function (lambda ( x ) (nth x g))) (vl-sort-i g (function (lambda ( a b ) (< (caadr a) (caadr b)))))) r)) ) (apply (function append) r) ) And Lee's variant : (defun mysort ( l ) (mapcar (function (lambda ( x ) (nth x l) ) ) (vl-sort-i l (function (lambda ( a b ) (if (eq (caar a) (caar b)) (< (caadr a) (caadr b)) (< (vl-prin1-to-string (caar a)) (vl-prin1-to-string (caar b))) ) ) ) ) ) ) Quote
Lee Mac Posted June 11, 2017 Posted June 11, 2017 @Lee, both codes may fail if list contains exactly equal elements... How so? vl-sort only removes duplicate integers. _$ (vl-sort '("a" "c" "f" "a" "h" "b" "e" "d" "g" "h") '<) ("a" "a" "b" "c" "d" "e" "f" "g" "h" "h") _$ (vl-sort '(3.5 1.5 6.5 1.5 4.5 3.5) '<) (1.5 1.5 3.5 3.5 4.5 6.5) _$ (vl-sort '((2 1) (1 1) (1 2) (2 1) (1 1) (4 5) (5 4)) '(lambda ( a b ) (if (= (car a) (car b)) (< (cadr a) (cadr b)) (< (car a) (car b))))) ((1 1) (1 1) (1 2) (2 1) (2 1) (4 5) (5 4)) _$ (vl-sort '(4 5 3 2 1 6 4 2 1 1 2) '<) (1 2 3 4 5 6) Quote
marko_ribar Posted June 11, 2017 Posted June 11, 2017 Lee, you'll have to test it on OP's example - I think ENAMEs are making elements behave like integers... Check it and you'll see... Quote
marko_ribar Posted June 11, 2017 Posted June 11, 2017 Actually this form of elements - list type are making that vl-sort eliminates them just like integers... Command: (setq l '(((1.0) (1.0)) ((1.0) (2.0)) ((3.0) (1.0)) ((3.0) (0.5)))) (((1.0) (1.0)) ((1.0) (2.0)) ((3.0) (1.0)) ((3.0) (0.5))) Command: (setq l (cons (car l) l)) (((1.0) (1.0)) ((1.0) (1.0)) ((1.0) (2.0)) ((3.0) (1.0)) ((3.0) (0.5))) Command: (setq l (cons (car l) l)) (((1.0) (1.0)) ((1.0) (1.0)) ((1.0) (1.0)) ((1.0) (2.0)) ((3.0) (1.0)) ((3.0) (0.5))) Command: (vl-sort l '(lambda ( a b ) (< (caadr a) (caadr b)))) (((3.0) (0.5)) ((1.0) (1.0)) ((3.0) (1.0)) ((1.0) (2.0))) Quote
marko_ribar Posted June 11, 2017 Posted June 11, 2017 Further more, if I may conclude - if elements are list type, they behave like integers while (vl-sort)... Here is example with point lists... It's just the point that when we draw points we rarely choose exactly the same coordinates, so (vl-sort) usually works well... Command: (setq l '((0.0 1.0 2.0) (1.0 2.0 3.0) (2.0 3.0 4.0))) ((0.0 1.0 2.0) (1.0 2.0 3.0) (2.0 3.0 4.0)) Command: (setq l (cons (car l) l)) ((0.0 1.0 2.0) (0.0 1.0 2.0) (1.0 2.0 3.0) (2.0 3.0 4.0)) Command: (setq l (cons (car l) l)) ((0.0 1.0 2.0) (0.0 1.0 2.0) (0.0 1.0 2.0) (1.0 2.0 3.0) (2.0 3.0 4.0)) Command: (vl-sort l '(lambda ( a b ) (< (car a) (car b)))) ((0.0 1.0 2.0) (1.0 2.0 3.0) (2.0 3.0 4.0)) Hope this explains things... Quote
handasa Posted June 11, 2017 Author Posted June 11, 2017 both worked fine ... thanks Mr.Marko , thanks Mr.lee Quote
Grrr Posted June 11, 2017 Posted June 11, 2017 if theres a risk that vl-sort removes duplicate elements, why not keep it safe: (defun mysort ( f L ) (mapcar (function (lambda (x) (nth x L))) (vl-sort-i L (function f))) ) _$ (mysort (lambda (a b) (< (cadr a) (cadr b))) '((0.0 1.0 2.0) (0.0 1.0 2.0) (0.0 1.0 2.0) (1.0 2.0 3.0) (2.0 3.0 4.0)) ) ((0.0 1.0 2.0) (0.0 1.0 2.0) (0.0 1.0 2.0) (1.0 2.0 3.0) (2.0 3.0 4.0)) _$ by using the above classical approach. Atleast I'm paranoid on just using (vl-sort) without testing its return on certain item types. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.