Author Topic: List enames of selection set  (Read 3768 times)

0 Members and 1 Guest are viewing this topic.

bgingerich

  • Guest
List enames of selection set
« on: April 11, 2013, 08:18:15 AM »
I'll start out by saying I'm just starting to learn lisp. 

Just for kicks and giggles I'm writing (or attempting) some functions that I can use in other lisps further down the road.  This particular one I'm struggling with returns a list of all the enames of objects in a given selection set.   I'm having trouble getting the (append... function to construct the list. 
Code: [Select]
(setq enamelist (append enamelist '(ssgetmember ss index)))

I know there must be a way to do this.  Maybe I shouldn't use (append, but (cons ... (reverse...)) ?  I don't know.

As I'm sure you can see SSLISTENAMES is supposed to return a list of enames and SSGETMEMBER returns the ename of a specified member of a selection set.

Code: [Select]
(defun SSLISTENAMES (SS / ENT LEN INDEX enamelist)
(if (setq LEN (sslength SS))
(progn
(setq index (1- len))
(while (> INDEX -1)
(setq enamelist (append enamelist '(ssgetmember ss index)))
(setq INDEX (1- INDEX))
) ;_ end of while
) ;_ end of progn
) ;_ end of if
enamelist
) ;_ end of defun

(defun SSGETMEMBER (SS INDEX / ENT LEN)
(if (and SS INDEX)
(while (> INDEX (1- (setq LEN (sslength SS))))
(princ
(strcat "Selection set only has " (rtos LEN 2 0) " objects. ")
) ;_ end of princ
(princ "\n")
(setq
INDEX
(getint
(strcat "Specify a number between 0 and "
(rtos (1- LEN) 2 0)
": "
) ;_ end of strcat
) ;_ end of getint
) ;_ end of setq
) ;_ end of while
) ;_ end of if
(setq ENT (nth 1 (car (ssnamex SS INDEX))))
) ;_ end of defun

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: List enames of selection set
« Reply #1 on: April 11, 2013, 08:45:43 AM »
Step through the selection set backwards, then do a cons. That way you need not do a reverse.
Code - Auto/Visual Lisp: [Select]
  1. (defun ss->list (ss / n result)
  2.   (repeat (setq n (sslength ss))
  3.     (setq result (cons (ssname ss (setq n (1- n))) result)))
  4.   result)
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

bgingerich

  • Guest
Re: List enames of selection set
« Reply #2 on: April 11, 2013, 08:59:35 AM »
Step through the selection set backwards, then do a cons. That way you need not do a reverse.
Code - Auto/Visual Lisp: [Select]
  1. (defun ss->list (ss / n result)
  2.   (repeat (setq n (sslength ss))
  3.     (setq result (cons (ssname ss (setq n (1- n))) result)))
  4.   result)

Thanks!  I had been stepping through backwards, but I forgot that if I did that there is no need for reverse. 

PS.  Is the repeat faster/better than while?  I would think it is because while has to evaluate one more expression each time.

BlackBox

  • King Gator
  • Posts: 3770
Re: List enames of selection set
« Reply #3 on: April 11, 2013, 09:28:34 AM »
PS.  Is the repeat faster/better than while?  I would think it is because while has to evaluate one more expression each time.

Speed test:

Code - Auto/Visual Lisp: [Select]
  1. (defun _repeat (ss / n result)
  2.   (repeat (setq n (sslength ss))
  3.     (setq result (cons (ssname ss (setq n (1- n))) result))
  4.   )
  5.   result
  6. )
  7.  
  8. (defun _while (ss / n e result)
  9.   (setq n -1)
  10.   (while (setq e (ssname ss (setq n (1+ n))))
  11.     (setq result (cons e result))
  12.   )
  13.   result
  14. )
  15.  
  16. (bench '(_repeat _while) (list (ssget)) 10000)
  17.  

Results:
Code - Text: [Select]
  1. _REPEAT
  2. Elapsed: 1263
  3. Average: 0.1263
  4.  
  5. _WHILE
  6. Elapsed: 1170
  7. Average: 0.1170
  8.  
  9. _$
  10.  

... Looks like While wins by a small margin, but the number of iterations for that small difference is moot.
"How we think determines what we do, and what we do determines what we get."

hmspe

  • Bull Frog
  • Posts: 367
Re: List enames of selection set
« Reply #4 on: April 11, 2013, 09:32:04 AM »
To directly address your question, there is a difference between
Code: [Select]
'(ssgetmember ss index)and
Code: [Select]
(list ssgetmember ss index)
Test code:
Code: [Select]
(defun SSLISTENAMES (ss / index enamelist1 enamelist2)
  (if ss
    (progn
      (setq index     (1- (sslength ss))                                     
            enamelist nil
      )                         
      (while (> index -1)
(setq enamelist1 (append enamelist1 '(ssname ss index)))   ;
(setq enamelist2 (append enamelist2 (list (ssname ss index))))   ;
(setq index (1- index))
      )
    )
  )
  (print "enamelist1")
  (print enamelist1)
  (print "enamelist2")
  (print enamelist2)
  (princ)
)
"Science is the belief in the ignorance of experts." - Richard Feynman

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: List enames of selection set
« Reply #5 on: April 11, 2013, 10:23:51 AM »
The main benefits of (while ...) are the extensive conditional testing to allow for early exits, and the ability to process a list in reverse, every other/third item, or other non-linear increments.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: List enames of selection set
« Reply #6 on: April 11, 2013, 12:35:42 PM »
http://www.theswamp.org/index.php?topic=14184.msg171131#msg171131
Another to try
Code: [Select]
(defun ss->lst (ss / i ename result)
  (and (eq 'pickset (type ss))
       (setq i (sslength ss))
       (while (setq ename (ssname ss (setq i (1- i))))
         (setq result (cons ename result))
       )
  )
  result
)

Code: [Select]
(defun c:test(/ ss)
  (setq ss (ssget))
  (print (sslength ss))
  (print (ssname ss 0))
  (setq lst (ss->lst ss))
  (print (length lst))
  (print (car lst))
  (princ)
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12928
  • London, England
Re: List enames of selection set
« Reply #7 on: April 11, 2013, 01:56:05 PM »
On this topic, my post regarding Selection Set Processing may be of interest.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: List enames of selection set
« Reply #8 on: April 11, 2013, 02:06:47 PM »
Nice write up. :)

I noticed you did not include this method.
Code: [Select]
(setq lst (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

bgingerich

  • Guest
Re: List enames of selection set
« Reply #9 on: April 11, 2013, 03:56:03 PM »
On this topic, my post regarding Selection Set Processing may be of interest.
http://www.theswamp.org/index.php?topic=14184.msg171131#msg171131
Another to try...

That's what I love about this place!  There is more and more information given!  Thank you guys for not just giving answers, but helping others to learn!

Lee Mac

  • Seagull
  • Posts: 12928
  • London, England
Re: List enames of selection set
« Reply #10 on: April 11, 2013, 05:43:39 PM »
Nice write up. :)

I noticed you did not include this method.
Code: [Select]
(setq lst (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))

Thanks CAB 8-)

I included a method based around the ssnamex function as 'Method 3', using a foreach loop to iterate over the list returned by this function, but felt it more efficient to test for enames during this iteration rather than iterate over the list three times (twice to obtain the enames, and a third to process the set).

Thanks for the feedback!

Lee Mac

  • Seagull
  • Posts: 12928
  • London, England
Re: List enames of selection set
« Reply #11 on: April 11, 2013, 05:44:25 PM »
That's what I love about this place!  There is more and more information given!  Thank you guys for not just giving answers, but helping others to learn!

You're very welcome bgingerich! :-)

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: List enames of selection set
« Reply #12 on: April 12, 2013, 01:24:45 AM »
It is something which is a bit strange about the repeat/while. But it's been tested a while back (about the ssnamex). Though it seems the vl-remove-if and mapcar is faster than the foreach with an if:
Code - Auto/Visual Lisp: [Select]
  1. (defun namex_CAB (ss) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))
  2.  
  3. (defun namex_LM ( s / r )
  4.   (foreach e (ssnamex s)
  5.     (if (= 'ename (type (cadr e)))
  6.       (setq r (cons (cadr e) r))))
  7.   (reverse r))
  8.  
  9. (defun namex_LM1 ( s / r )
  10.   (foreach e (ssnamex s)
  11.     (if (not (listp (cadr e)))
  12.       (setq r (cons (cadr e) r))))
  13.   (reverse r))
  14.  
  15. (defun _repeat (ss / n result)
  16.   (repeat (setq n (sslength ss))
  17.     (setq result (cons (ssname ss (setq n (1- n))) result)))
  18.   result)
  19.  
  20. (defun _while (ss / n e result)
  21.   (setq n -1)
  22.   (while (setq e (ssname ss (setq n (1+ n))))
  23.     (setq result (cons e result)))
  24.   result)
Test
Code: [Select]
_$ (setq *ss* (ssget "_X"))
<Selection set: ca>
_$ (sslength *ss*)
10000
_$ (quickbench '((namex_CAB *ss*) (namex_LM *ss*) (namex_LM1 *ss*) (_repeat *ss*) (_while *ss*)))
Benchmarking ..... done for 128 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(_WHILE *SS*)                                  128      1482      1482      6.99
(_REPEAT *SS*)                                  64      1031      2062      5.02
(NAMEX_CAB *SS*)                                32      1888      7552      1.37
(NAMEX_LM1 *SS*)                                16      1216      9728      1.06
(NAMEX_LM *SS*)                                 16      1295     10360      1.00
--------------------------------------------------------------------------------

Anyhow, the repeat/while difference gets reversed once you compile the LSP file:
Code: [Select]
_$ (vlisp-compile 'st "G:\\Documents\\AutoLisp Tests\\tmp.lsp")
T
_$ (load "G:\\Documents\\AutoLisp Tests\\tmp.fas")
_WHILE
_$ (quickbench '((namex_CAB *ss*) (namex_LM *ss*) (namex_LM1 *ss*) (_repeat *ss*) (_while *ss*)))
Benchmarking ..... done for 256 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(_REPEAT *SS*)                                 256      1888      1888      9.66
(_WHILE *SS*)                                  256      1935      1935      9.43
(NAMEX_CAB *SS*)                                32      1841     14728      1.24
(NAMEX_LM1 *SS*)                                16      1029     16464      1.11
(NAMEX_LM *SS*)                                 16      1140     18240      1.00
--------------------------------------------------------------------------------
The compile doesn't seem to do any optimizations for the ssnamex though.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: List enames of selection set
« Reply #13 on: April 12, 2013, 01:30:20 AM »
I even thought the difference between Lee's and CAB's ssnamex versions is because I added a reverse to Lee's (to make the result the same). But no, the reverse doesn't seem to matter:
Code - Auto/Visual Lisp: [Select]
  1. (defun namex_LM_ ( s / r )
  2.   (foreach e (ssnamex s)
  3.     (if (= 'ename (type (cadr e)))
  4.       (setq r (cons (cadr e) r))))
  5.   r)
  6.  
  7. (defun namex_LM1_ ( s / r )
  8.   (foreach e (ssnamex s)
  9.     (if (not (listp (cadr e)))
  10.       (setq r (cons (cadr e) r))))
  11.   r)

And the test:
Code: [Select]
_$ (quickbench '((namex_CAB *ss*) (namex_LM *ss*) (namex_LM1 *ss*) (namex_LM_ *ss*) (namex_LM1_ *ss*)))
Benchmarking ..... done for 32 iterations. Sorted from fastest.
Statement                                Increment  Time(ms) Normalize  Relative
--------------------------------------------------------------------------------
(NAMEX_CAB *SS*)                                32      1872      1872      1.40
(NAMEX_LM1 *SS*)                                16      1185      2370      1.11
(NAMEX_LM1_ *SS*)                               16      1185      2370      1.11
(NAMEX_LM *SS*)                                 16      1295      2590      1.01
(NAMEX_LM_ *SS*)                                16      1310      2620      1.00
--------------------------------------------------------------------------------
It's as if the reverse takes up no time at all. At least in comparison to ssnamex's slowness.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lee Mac

  • Seagull
  • Posts: 12928
  • London, England
Re: List enames of selection set
« Reply #14 on: April 12, 2013, 07:22:34 AM »
Though it seems the vl-remove-if and mapcar is faster than the foreach with an if...

I appreciate the testing Irné, though please note that my original post was regarding selection set processing, not converting a selection set to a list of entity names; my earlier point was that using the vl-remove-if / mapcar construction would require an addition foreach loop in order to processing the set (i.e. operate on the entity names), whereas using the single foreach allows for processing the set in a single loop.