Jump to content

Recommended Posts

Posted (edited)

Of the following examples which one is "better". ("better" because I'm sure there are many different viewpoints):

 

(setq ss (ssget "_x" (list (cons 0 "INSERT") (cons 8 "0"))))

or

 

(setq ss (ssget "_x" '((0 . "INSERT") (8 . "0"))))

Other than the second option being more compact than the first are there any other advantages to either one?

Edited by KRBeckman
missing parenthesis (thanks Lee Mac)
Posted

The first is better since the second is missing a parenthesis :P

Posted

haha... other than that?

 

Oh, and its fixed now.

Posted

Perhaps neither is 'better', both are valid. I suppose the second is more economical, since no functions need to be evaluated but that's about all.

 

I would use the second if no expressions within the filter list need be evaluated, else I would use the first.

 

Have a read of these:

 

http://www.cadtutor.net/forum/showthread.php?55337-My-first-lisp&p=375455&viewfull=1#post375455

http://www.cadtutor.net/forum/showpost.php?p=258390&postcount=20

Posted

(defun f1 ( / ss)(setq ss (ssget "_x" (list (cons 0 "INSERT") (cons 8 "0")))))
(defun f2 (/ ss)(setq ss (ssget "_x" '((0 . "INSERT") (8 . "0")))))

Test

(benchmark '( f1 f2))

Result

Benchmarking .......................Elapsed milliseconds / relative speed for 1048576 iteration(s):

 

F2.....2032 / 1.03

F1.....2093 / 1.00

Benchmark code

Posted

I'd have expected that. As Lee's already explained F2 evaluates a lot less than F1 does. It's as if F2 simply sets the filter list to its values, F1 constructs a new list from separate values.

 

To answer the OP (if Lee's explanation was too "cryptic" :wink:): The quoted list is the "best" (read most efficient) way to use if (and only if) all the values inside the list never change. If any one of those values must be read from somewhere else your only option is to use the list & cons idea - since you need to create a list by combining changeable values. As an example, take the following situation:

 

You want to work on all block references placed on layer 0. Then F2 can be used without any trouble.

 

BUT! Say you first ask the user to enter the layer name (or pick an entity to choose the layer). Then you have to use F1 since you'd be "reading" the 8 DXF-code from the picked entity and you don't know it beforehand. In this case you could "combine" the 2 versions thus:

(setq en (entsel "Pick source entity:") ed (entget (car en)))
(setq ss (ssget "_X" (list '(0 . "INSERT") (assoc 8 ed))))

Note I'm not cdr'ing the assoc and then cons'ing it back with an 8, since this would not be necessary - but if the user had totype in the layer name, then you'd have needed to cons the typed in value with an 8.

Posted

^^ That, along with those links I provided should provide a full understanding I would think - thanks Irneb :)

 

Also, notice that the difference is for most cases negligible:

 

Benchmarking .......................Elapsed milliseconds / relative speed for 1048576 iteration(s):

 

F2.....2032 / 1.03

F1.....2093 / 1.00

Posted

Hello all,

when comparing two ways just for their elapsed time, you are right that the second one is faster, but what about these two conditions?

1:

(foreach otype '("LINE" "ARC" "CIRCLE" "INSERT" "*TEXT")

(setq ss (ssget "_x" (list (cons 0 otype) (cons 8 "0"))))

...

) :lol:

 

2:

(setq ss (ssget "_x" '((0 . ("LINE") (8 . "0"))))

...

(setq ss (ssget "_x" '((0 . "ARC") (8 . "0"))))

...

(setq ss (ssget "_x" '((0 . "CIRCLE" ) (8 . "0"))))

...

(setq ss (ssget "_x" '((0 . "INSERT" ) (8 . "0"))))

...

(setq ss (ssget "_x" '((0 . "*TEXT") (8 . "0"))))

...:cry:

Posted

Or even this?

(setq ss (ssget "_X" '((0 . "LINE,ARC,CIRCLE,INSERT,*TEXT") (8 . "0"))))

Posted
Or even this?
(setq ss (ssget "_X" '((0 . "LINE,ARC,CIRCLE,INSERT,*TEXT") (8 . "0"))))

You are right, but I always use (list (cons 0 otype)) when the otype is defined on the fly.

Posted

I believe Irneb was indicating the use of the wildcard string, using comma's to separate the entity types.

Posted
I believe Irneb was indicating the use of the wildcard string, using comma's to separate the entity types.
Correct. Since Ahankhah was asking about 2 alternatives' speed, I showed one method which would definitely be "much" quicker.

 

However, trying to get the wildcard matching from combining on the fly may possibly take longer than Ahankhah's 2nd option (depending on the number of entities to select in the DWG). The reason for saying so is that on the fly you'd need to concatenate the oTypes into a string, and Lisp's strcat is not exactly the most efficient way of doing so. E.g.

(setq oTypeLst '("LINE" "ARC" "CIRCLE" "INSERT" "*TEXT"))
(setq ss (ssget "_X" (list (apply 'strcat (cons (car oTypeLst) (mapcar '(lambda (e) (strcat "," e)) (cdr oTypeLst)))))))

Of course Ahankhah's methods would give you separate selection sets, one for each object type. Mine give one combined selection set. It depends on what you want to do with these after you've gotten hold of the selection set(s). It may be more efficient with Ahankhah's method if you have to do something different depending on what object type it is, in this case you'd need to test for the oType a 2nd time using mine.

 

So this is actually an example of optimizing too much (depending on situation). I.e. I've optimized the ssget portion to near perfection, but in the process caused extra work later on. And since the speed differences between these method are so infinitesimal, it's actually quite counter-intuitive. A bit of "Penny-Wise-Pound-Foolish" :unsure:.

 

You see, the way you generate the filter list is a minuscule portion of the ssget itself. And nearly always the actual time wasting is going to happen after ssget has completed (i.e. when you actually work on the items inside ss). So rather do the ssget thing in order to optimize what comes thereafter, if there's no difference either way - then by all means optimize that 1000ths of a second out of your code.

 

Although there's a caveat: You're only allowed a small number of active selection sets at one time. You get errors if you surpass this. And even though you reuse ss for the following ssgets, they may not have cleared from RAM yet.

Posted
...and Lisp's strcat is not exactly the most efficient way of doing so...

 

Attempting to avoid the strcat call...

 

(defun makefilter ( lst )
 (apply 'strcat (cons (car lst) (mapcar '(lambda (e) (strcat "," e)) (cdr lst))))
)

 

(defun makefilter2 ( lst )
 (vl-list->string
   (apply 'append
     (cons (car (setq lst (mapcar 'vl-string->list lst)))
       (mapcar
         (function
           (lambda ( x ) (cons 44 x))
         )
         (cdr lst)
       )
     )
   )
 )
)

 

(setq l '("AB" "CD" "EF" "GH" "IJ" "KL" "MN" "OP" "QR" "ST" "UV" "WX" "YZ"))

 

Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s):

   (MAKEFILTER2 L).....1716 / 1.07 <fastest>
   (MAKEFILTER L)......1840 / 1.00 <slowest>

 

(repeat 10 (setq l (append l l)))

 

Benchmarking .............Elapsed milliseconds / relative speed for 1024 iteration(s):

   (MAKEFILTER2 L).....1248 / 1.61 <fastest>
   (MAKEFILTER L)......2012 / 1.00 <slowest>

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