Jump to content

vl-sort kinda sucks


j2lstaples

Recommended Posts

This is just caution for those of you who would like to sort your lists of any kind. If you're dealing with integers in your compare function, vl-sort will ruin your list.

 

I have a very simple test case for this. Suppose:

(setq lst '(0 0 0 1 0 0 0))

And you want to sort this list such that:

sort-list = (0 0 0 0 0 0 1)

You think you would use a simple implementation of vl-sort like the following:

(setq sort-list (vl-sort lst '(lambda (s1 s2) (<= s1 s2))))

It seems alright and you even considered that two values might be the same. So, fine and dandy, right? WRONG

What this will show is that:

sort-list = (0 1)

Now you lost information. 

 

Now, you might be working with a list of entity names and you use the compare function.

'(lambda (s1 s2) (<= 	(atoi (LM:vl-getattributevalue (vlax-ename->vla-object s1) "ITEM_NO")
			(atoi (LM:vl-getattributevalue (vlax-ename->vla-object s2) "ITEM_NO")))

 

How will you be able to know that it didn't just skip or remove a block from your sorted list. Should you even trust this function? *end of rant*

Link to comment
Share on other sites

You'd have to use something like what Kent1Cooper on the AutoCAD forums posted: 

 

(mapcar 'cdr (vl-sort (mapcar '(lambda (x) (cons 1 x)) lst) '(lambda (y z) (< (cdr y) (cdr z)))))

 

Link to comment
Share on other sites

Using Vl-sort need to take into account type of items in list strings, real and integers, or combinations. So theVL-sort is slightly different. 

 

You can sort a list to multiple depths I have some code taht looks at up to the first 5 items in a list used with extract quantities.

 

;x only
(setq lst (vl-sort lst '(lambda (x y) (< (car x)(car y)))))

(vl-sort '(3 2 1 20 98.32 16 0 20 -2.345) '<)
(-2.345 0 1 2 3 16 20 98.32) only 1 20

(setq test '(87 6.54 20 1 8.88 20))   ; contains two 20's
(mapcar 'cdr (vl-sort (mapcar '(lambda (x) (cons 1 x)) test) '(lambda (y z) (< (cdr y) (cdr z)))))
returns:
(1 6.54 8.88 20 20 87); both 20's still there
  
; sorts on 1st two items
(vl-sort lst
	 '(lambda (a b)
	    (cond
	      ((< (car a) (car b)))
	      ((= (car a) (car b)) (< (cadr a) (cadr b)))
	    )
	  )
)

 

  • Agree 1
Link to comment
Share on other sites

Iterative version :

 

(defun _vl-sort ( l f / *q* ll ff gg )
  (if (= (type f) 'sym)
    (setq f (eval f))
  )
  (while (setq *q* (car l))
    (setq ll
      (if (null ll)
        (cons *q* ll)
        (cond
          ( (apply f (list (last ll) *q*))
            (append ll (list *q*))
          )
          ( (apply f (list *q* (car ll)))
            (cons *q* ll)
          )
          ( t
            (setq ff nil)
            (setq gg (apply (function append)
              (append (mapcar (function (lambda ( *xxx* *yyy* )
                (if (null ff)
                  (if (apply f (list *q* *yyy*))
                    (progn (setq ff t) (list *xxx* *q*))
                    (list *xxx*)
                  )
                  (list *xxx*)
                )
              )) ll (cdr ll)
              ) (list (list (last ll)))
              ))
            )
            (if (null ff)
              (append ll (list *q*))
              gg
            )
          )
        )
      )
    )
    (setq l (cdr l))
  )
  ll
)

 

HTH., M.R.

Edited by marko_ribar
Link to comment
Share on other sites

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