Jump to content

Recommended Posts

Posted

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

Posted (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 by marko_ribar
Posted

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)
)

Posted

@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)))
         )
       )
     )
   )
 )
)

Posted
@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)

Posted

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...

Posted

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)))

Posted

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...

Posted

both worked fine ... thanks Mr.Marko , thanks Mr.lee :D :o

Posted

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.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...