Jump to content

Average, Min, Max


johnengineer

Recommended Posts

  • Replies 25
  • Created
  • Last Reply

Top Posters In This Topic

  • Lee Mac

    13

  • CAB

    4

  • johnengineer

    3

  • ReMark

    2

If you have no luck on Cadalyst, try this, something I typed up a second ago o:)

 

 ; Max, Min and Average by Lee McDonnell -- 12/08

(defun c:number    (/ ans ent1 nmax ent num ent2 nmin ent3 num2 ss ssl index tents tot ent4 num3 ave)
   (princ "\nInitializing...")
   (initget 1 "Max Min Average")
   (setq ans (getkword "\nSpecify Numerical Requirement [MAx/MIn/Ave]: "))
   (cond
   ((= ans "Max")
    (if
        (setq ent1 (car (entsel "\nSelect Numerical Text: ")))
       (progn
           (setq nmax (atof (cdr (assoc 1 (entget ent1)))))
           (while
           (/= (setq ent (car (entsel "\nSelect Numerical Text: "))) nil)
              (if (= (cdr (assoc 0 (entget ent))) "TEXT")
                  (progn
                  (setq num (atof (cdr (assoc 1 (entget ent)))))
                  (if (> num nmax)
                      (setq nmax num)
                  ) ;_  end if
                  ) ;_  end progn
                  (alert "Selected Entity must be Text.")
              ) ;_  end if
           ) ;_  end while
           (alert (strcat "Maximum Number is: " (rtos nmax)))
       ) ;_  end progn
       (alert "Text Required.")
    ) ;_  end if
   )
   ((= ans "Min")
    (if
        (setq ent2 (car (entsel "\nSelect Numerical Text: ")))
       (progn
           (setq nmin (atof (cdr (assoc 1 (entget ent2)))))
           (while
           (/= (setq ent3 (car (entsel "\nSelect Numerical Text: "))) nil)
              (if (= (cdr (assoc 0 (entget ent3))) "TEXT")
                  (progn
                  (setq num2 (atof (cdr (assoc 1 (entget ent3)))))
                  (if (< num2 nmin)
                      (setq nmin num2)
                  ) ;_  end if
                  ) ;_  end progn
                  (alert "Selected Entity must be Text.")
              ) ;_  end if
           ) ;_  end while
           (alert (strcat "Minimum Number is: " (rtos nmin)))
       ) ;_  end progn
       (alert "Text Required.")
    ) ;_  end if
   )
   ((= ans "Average")
    (setq ss    (ssget)
          ssl   (sslength ss)
          index 0
          tents 0
          tot   0
    ) ;_  end setq
    (repeat ssl
        (setq ent4 (entget (ssname ss index)))
        (if (= (cdr (assoc 0 ent4)) "TEXT")
        (progn
            (setq num3 (atof (cdr (assoc 1 ent4))))
            (setq tot (+ num3 tot))
            (setq tents (1+ tents))
        ) ;_  end progn
        ) ;_  end if
        (setq index (1+ index))
    ) ;_  end repeat
    (if (/= tents 0)
        (progn
        (setq ave (/ tot tents))
        (alert (strcat "Average of " (rtos tents) " Numbers is: " (rtos ave)))
        ) ;_  end progn
        (alert "No Text Entities Selected.")
    ) ;_  end if
   )
   ) ;_  end cond
   (princ)
) ;_  end defun

Link to comment
Share on other sites

I'm not all that pleased with the "entsel" method for selecting the text entities in the Max and Min operations - I would prefer to again use an ssget selection method.

 

But the problem I am coming up against is that in a min, max operation one may need a benchmark for comparison, i.e. take one figure in the set and then compare the other figures to it and if each is larger or smaller than the benchmark, then set it as the new benchmark and so on. So I thought about using the first element of the selection set as the benchmark, but this does not discard the possibility that the first element is maybe not a text element.

I think I could engineer a program to do this but, I need more time - use the above for the time being. :P

Link to comment
Share on other sites

I think I could engineer a program to do this but, I need more time - use the above for the time being. :P

 

Unacceptable Lee. We need that fix now or you're not getting paid!:x :x :x

 

 

P.S. :P

Link to comment
Share on other sites

Slacker:lol: :lol: :lol:

 

Lee:

 

First. You knock these things out with such ease I'm jealous. You really seem to have a knack for lisp.:thumbsup:

 

Second. Do you ever sleep?

Link to comment
Share on other sites

First. You knock these things out with such ease I'm jealous. You really seem to have a knack for lisp.:thumbsup:

 

Thanks :P - I get a lot of practice on here :P

 

Second. Do you ever sleep?

 

Rarely, I must admit... :P

Link to comment
Share on other sites

Thanks for your help Lee Mac. I agree with you on the "entsel" method of selecting the text entities. I have hundreds of text entitites which makes it impractical to do.

Link to comment
Share on other sites

Ok John, I had a couple of minutes, try this:

 

 ; Max, Min and Average by Lee McDonnell -- 12/08

(defun c:number    (/       ans         ss_max    ssl_max     xth       tent_max  ent_max   ent_base_max
        num_max   ss_min    ssl_min   yth     tent_min  ent_min   ent_base_min
        num_min   ss         ssl       index     tents       tot         ent       num
        ave
       )

   (princ "\nInitializing...")
   (initget 1 "Max Min Average")
   (setq ans (getkword "\nSpecify Numerical Requirement [MAx/MIn/Ave]: "))
   (cond
   ((= ans "Max")
    (setq ss_max    (ssget)
          ssl_max    (sslength ss_max)
          xth    0
          tent_max    0
    ) ;_  end setq
    (if (/= ssl_max 0)
        (progn
        (while    (< xth ssl_max)
            (setq ent_max (entget (ssname ss_max xth)))
            (if (= (cdr (assoc 0 ent_max)) "TEXT")
            (progn
                (setq ent_base_max (atof (cdr (assoc 1 ent_max))))
                (setq xth ssl_max)
            ) ;_  end progn
            (setq xth (1+ xth))
            ) ;_  end if
        ) ;_  end while
        (setq xth 0)
        (repeat ssl_max
            (setq ent_max (entget (ssname ss_max xth)))
            (if (= (cdr (assoc 0 ent_max)) "TEXT")
            (progn
                (setq num_max (atof (cdr (assoc 1 ent_max))))
                (if (> num_max ent_base_max)
                (setq ent_base_max num_max)
                ) ;_  end if
                (setq tent_max (1+ tent_max))
            ) ;_  end progn
            ) ;_  end if
            (setq xth (1+ xth))
        ) ;_  end repeat
        (alert (strcat "Maximum of " (rtos tent_max) " Numbers is: " (rtos ent_base_max)))
        ) ;_  end progn
        (alert "No Entities Selected.")
    ) ;_  end if
   )
   ((= ans "Min")
    (setq ss_min    (ssget)
          ssl_min    (sslength ss_min)
          yth    0
          tent_min    0
    ) ;_  end setq
    (if (/= ssl_min 0)
        (progn
        (while    (< yth ssl_min)
            (setq ent_min (entget (ssname ss_min yth)))
            (if (= (cdr (assoc 0 ent_min)) "TEXT")
            (progn
                (setq ent_base_min (atof (cdr (assoc 1 ent_min))))
                (setq yth ssl_min)
            ) ;_  end progn
            (setq yth (1+ yth))
            ) ;_  end if
        ) ;_  end while
        (setq yth 0)
        (repeat ssl_min
            (setq ent_min (entget (ssname ss_min yth)))
            (if (= (cdr (assoc 0 ent_min)) "TEXT")
            (progn
                (setq num_min (atof (cdr (assoc 1 ent_min))))
                (if (< num_min ent_base_min)
                (setq ent_base_min num_min)
                ) ;_  end if
                (setq tent_min (1+ tent_min))
            ) ;_  end progn
            ) ;_  end if
            (setq yth (1+ yth))
        ) ;_  end repeat
        (alert (strcat "Minimum of " (rtos tent_min) " Numbers is: " (rtos ent_base_min)))
        ) ;_  end progn
        (alert "No Entities Selected.")
    ) ;_  end if
   )
   ((= ans "Average")
    (setq ss    (ssget)
          ssl   (sslength ss)
          index 0
          tents 0
          tot   0
    ) ;_  end setq
    (repeat ssl
        (setq ent (entget (ssname ss index)))
        (if (= (cdr (assoc 0 ent)) "TEXT")
        (progn
            (setq num (atof (cdr (assoc 1 ent))))
            (setq tot (+ num tot))
            (setq tents (1+ tents))
        ) ;_  end progn
        ) ;_  end if
        (setq index (1+ index))
    ) ;_  end repeat
    (if (/= tents 0)
        (progn
        (setq ave (/ tot tents))
        (alert (strcat "Average of " (rtos tents) " Numbers is: " (rtos ave)))
        ) ;_  end progn
        (alert "No Text Entities Selected.")
    ) ;_  end if
   )
   ) ;_  end cond
   (princ)
) ;_  end defun

Link to comment
Share on other sites

(defun c:textvals (/ ss i tv vl)
  (while (not ss)
         (princ "\nSelect Text To Calulate...")
         (setq ss (ssget '((0 . "TEXT")))))
  (setq i (sslength ss))
  (while (not (minusp (setq i (1- i))))
         (setq tv (cdr (assoc 1 (entget (ssname ss i)))))
         (setq vl (cons (atof tv) vl)))
  (setq min_val (apply 'min vl)
        max_val (apply 'max vl)
        avg_val (/ (apply '+ vl) (length vl)))
  (prin1))

 

You have some gotchas here:

 

Do you need to test for MTEXT entities?

 

You need to test for 0-9 characters and decimal points in the text.

Are there any comas allowed?

A (wcmatch) could do that but it is a bit clunky.

 

You might need to filter out paperspace/modelspase entities

 

There are probably a few more that could get you as well. -David

Link to comment
Share on other sites

I am very impressed with your code David and wish to learn a lot from it. I understand the majority of the code, except this line:

 

         (setq vl (cons (atof tv) vl)))

 

I understand that you are creating a list of all the numbers in the selection set, but how does it treat the initial value of "vl"?

 

i.e. would you not be left with for example, if the text contained:

 

1,2,3,4,5:

 

(1 2 3 4 5 [b]nil[/b])

or something similar, as the with the initial value (nil) of vl in there?

 

Thanks in advance for any help :)

Link to comment
Share on other sites

Lee,

 

The value of nil is an empty list ().

Command: (null nil)
T

Command: (listp nil)
T

 

That is one reason it is so important to declare variables as local when dealing with lists. Otherwise, you get erroneous results due to the fact that the variable is already bound to a list.

 

Command: (setq vl nil)
nil

Command: (setq vl (cons 2 vl))
(2)

-David

Link to comment
Share on other sites

Nice one. Thanks, I understand it much better now.

 

The thing that was restricting me when I created my LISP was how to turn a selection set into a list. - I really wanted to use the in built "min" and "max" functions in LISP, but because I didn't know how to turn the selection set into a list, I had to improvise and make up my own way of finding the maximum.

 

I also like the way that your LISP only asks for one selection set and deals with things from there - makes things much simpler.

Link to comment
Share on other sites

Here is another example using a selection set.

(defun c:test (/ ss lst numlst txt2num)
 (defun txt2num (txt / num)
   (or (setq num (distof txt 5))
       (setq num (distof txt 2))
       (setq num (distof txt 1))
       (setq num (distof txt 4))
       (setq num (distof txt 3))
   )
   num
 )
 (prompt "\nSelect text to analize numbers.")
 (if (setq ss (ssget '((0 . "TEXT,MTEXT"))))
   (progn
     (setq lst (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))))
     (mapcar '(lambda (x) (setq numlst (cons (txt2num (cdr (assoc 1 (entget x)))) numlst)))
             lst
     )
     (if (setq numlst (vl-remove-if 'listp numlst))
       (progn
         (print "Min number ")
         (princ (apply 'min numlst))
         (print "Max number ")
         (princ (apply 'max numlst))
         (print "Average of numbers ")
         (princ (/ (apply '+ numlst) (length numlst)))
       )
       (prompt "\nNo numberf found.")
     )
   )
 )
 (princ)
)

Link to comment
Share on other sites

Thanks Lee,

 

distof is more forgiving as to the format of the string.

I almost always use getdist as well for that reason.

Also see attached a more verbose routine.

 

Here is another example:

  ;; convert to a number & return (number & type)
 (defun gettype (str / num typ)
              ;;  must be tested in this order (2 1 5 4 3)
              ;; if you use (1 2 3 4 5) you will not get any 2 4 or 5 results
              ;;  further test result in inconsistancies with 3&4 and 5 types
              (cond ((setq num (distof str 2))
                     (setq typ 2)
                    )
                    ((setq num (distof str 1))
                     (setq typ 1)
                    )
                    ((setq num (distof str 5))
                     (setq typ 5)
                    )
                    ((setq num (distof str 3))
                     (setq typ 3)
                    )
                    ((setq num (distof str 4))
                     (setq typ 4)
                    )
                    ((setq num (read str))
                     ;;  (setq typ 6)  return nil for this type
                    ) ; get number if followed by a space "10 a" = 10
                    ;; (read "10a") = "10a" so you must test result with
                    ;;   (numberp "10a") results in 'not a number'
              )
   (if typ
     (list num typ)
     )
)

Text2Num CAB 2-1.LSP

Link to comment
Share on other sites

Ahh, I understand it better now. Thanks.

 

And I must say, that LISP you attached is absolutely phenomenal! - so well written (not that I understood most of it)... but brilliant all the same :)

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