KRBeckman Posted March 4, 2011 Posted March 4, 2011 (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 March 4, 2011 by KRBeckman missing parenthesis (thanks Lee Mac) Quote
Lee Mac Posted March 4, 2011 Posted March 4, 2011 The first is better since the second is missing a parenthesis Quote
KRBeckman Posted March 4, 2011 Author Posted March 4, 2011 haha... other than that? Oh, and its fixed now. Quote
Lee Mac Posted March 4, 2011 Posted March 4, 2011 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 Quote
VVA Posted March 5, 2011 Posted March 5, 2011 (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 Quote
irneb Posted March 5, 2011 Posted March 5, 2011 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. Quote
Lee Mac Posted March 5, 2011 Posted March 5, 2011 ^^ 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 Quote
Ahankhah Posted March 5, 2011 Posted March 5, 2011 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")))) ... ) 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")))) ... Quote
irneb Posted March 5, 2011 Posted March 5, 2011 Or even this? (setq ss (ssget "_X" '((0 . "LINE,ARC,CIRCLE,INSERT,*TEXT") (8 . "0")))) Quote
Ahankhah Posted March 6, 2011 Posted March 6, 2011 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. Quote
Lee Mac Posted March 6, 2011 Posted March 6, 2011 I believe Irneb was indicating the use of the wildcard string, using comma's to separate the entity types. Quote
irneb Posted March 6, 2011 Posted March 6, 2011 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" . 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. Quote
Lee Mac Posted March 6, 2011 Posted March 6, 2011 ...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> 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.