sorting a list of layers

sorting a list of layers

pyreflos
Participant Participant
355 Views
4 Replies
Message 1 of 5

sorting a list of layers

pyreflos
Participant
Participant

I have the following and it works well, but I want to sort if into alphabetical order:

  (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
  (setq laycoll (vla-get-layers adoc))
  (vlax-for lay laycoll
    (setq layn (vla-get-Name lay))
    (if (not (wcmatch layn "*|*"))
      (progn
        (if (= (vla-get-freeze lay) :vlax-true)
          (progn
            (setq freezelst (cons (vla-get-name lay) freezelst))
            (vla-put-freeze lay :vlax-false)
          )
        )
    (setq layd (vla-get-Description lay))
    (setvar "clayer" layn)
    (command "line" (list dx1 dyy) (list dx2 dyy) "")
    (command "text" "s" "Arial" "j" "ml" (list dx3 dyy) "8" "0" layn)
    (command "text" "j" "ml" (list dx4 dyy) "8" "0" layd)
    (setq dyy(cadr(polar (list dx1 dyy) (* pi 1.5) dyi)))
  )
)
)

 I tried putting the following line after setq layn (line 4), but I get the error bad argument type listp:

(vl-sort layn '<)

I'm pretty rusty on coding, so I'm a little lost. '< appears to be the wrong argument, but I'm not sure what to use.

0 Likes
356 Views
4 Replies
Replies (4)
Message 2 of 5

devitg
Advisor
Advisor

@pyreflos 

Vl-sort apply to list 

 

 

Just search at VLIDE help 

 

vl-sort (AutoLISP)

Sorts the elements in a list according to a given compare function

Supported Platforms: Windows and Mac OS

Signature

(vl-sort lst comparison-function)
lst
Type: List

Any list to sort.

comparison-function
Type: Subroutine or Symbol

A comparison function. This can be any function that accepts two arguments and returns T (or any non-nil value) if the first argument precedes the second in the sort order. The comparison-function value can take one of the following forms:

A symbol (function name)
'(LAMBDA (A1 A2) ...)
(FUNCTION (LAMBDA (A1 A2) ...))
Return Values

Type: List

A list containing the elements of lst in the order specified by comparison-function. Duplicate elements may be eliminated from the list.

Examples

Sort a list of numbers:

(vl-sort '(3 2 1 3) '<)
(1 2 3)
Note that the result list contains only one 3.

Sort a list of 2D points by Y coordinate:

(vl-sort '((1 3) (2 2) (3 1))
             (function (lambda (e1 e2)
                         (< (cadr e1) (cadr e2)))))
((3 1) (2 2) (1 3))
Sort a list of symbols:

(vl-sort
   '(a d c b a)
   '(lambda (s1 s2)
    (< (vl-symbol-name s1) (vl-symbol-name s2))))
(A B C D)       ;  Note that only one A remains in the result list

 

Message 3 of 5

pyreflos
Participant
Participant

Ok. So I should be using 'lambda instead of '<. Do you have any good examples of how that works? I don't really understand how to apply the lambda function to a list of layer names...

0 Likes
Message 4 of 5

Sea-Haven
Mentor
Mentor

Like devitg example

 

(setq lst (vl-sort lst '(lambda (x y) (< (car x)(car y)))))
0 Likes
Message 5 of 5

ВeekeeCZ
Consultant
Consultant

@pyreflos 

 

You need to rewrite the algorithm. 

 

The current one is

- get a collection of layer vla-objects

- (now you should sort them, but that is not efficient, can't sort the vla-objects directly... you will need their names for it)

- for each layer: thaw layer if needed, add to list, create line+text

 

You need 

- get a layer collection

- for each layer object: thaw layer if needed, add to a reduced list of pairs of '(name . desc)

- sort the reduced list by the names

- for each pair of the reduced list: create line+text

 

You could really use simple (vl-sort layerlist '<) but just in case it was a simple list of layers (of sortable items) like '("Layer3" "Layer1" "Layer5").

(vl-sort layerlist '<) which equals to (vl-sort freezelst '(lambda (x y) (< x y))) in more general form using an anonymous function.

 

But for the final solution, we have a list of pairs (name . desc). You can't compare them directly, you need to get a name from a pair. So you need to add CAR.

(vl-sort freezelst '(lambda (x y) (< (car x) (car y)). Simple form can't be used.

 

Something like this, untested:

 

  (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
  (setq laycoll (vla-get-layers adoc))
  (vlax-for lay laycoll
    (setq layn (vla-get-Name lay))
    (if (and (not (wcmatch layn "*|*"))
	     (= (vla-get-freeze lay) :vlax-true)
	     (setq freezelst (cons (cons (vla-get-name lay)	; create list of pairs '((layername . layerdesc))
					 (vla-get-Description lay))
				   freezelst))
	     )
      (vla-put-freeze lay :vlax-false)))
  
  (setq freezelst (vl-sort freezelst '(lambda (x y) (< (car x) (car y))))) ; sort list of pairs by 1st item of pair - thats why there is CAR
  
  (foreach pair freezelst
    
    (setq layn (car pair)
	  layd (cadr pair))
    
    (setvar "clayer" layn)
    (command "line" (list dx1 dyy) (list dx2 dyy) "")
    (command "text" "s" "Arial" "j" "ml" (list dx3 dyy) "8" "0" layn)
    (command "text" "j" "ml" (list dx4 dyy) "8" "0" layd)
    (setq dyy (cadr(polar (list dx1 dyy) (* pi 1.5) dyi)))
    )

 

Don't forget that freezelst needs to be localized !!

0 Likes