johnengineer Posted December 17, 2008 Share Posted December 17, 2008 Can someone help me find a lisp to find the average, min, and max of text with numerical values? Quote Link to comment Share on other sites More sharing options...
ReMark Posted December 17, 2008 Share Posted December 17, 2008 There is an entire archive of Lisp routines at CAD TIPS which is part of the cadalyst magazine website. I've conducted many a search there in response to questions asked here. Give it a try. Start here: www.cadalyst.com Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 18, 2008 Share Posted December 18, 2008 If you have no luck on Cadalyst, try this, something I typed up a second ago ; 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 Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 18, 2008 Share Posted December 18, 2008 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. Quote Link to comment Share on other sites More sharing options...
MaxwellEdison Posted December 18, 2008 Share Posted December 18, 2008 I think I could engineer a program to do this but, I need more time - use the above for the time being. Unacceptable Lee. We need that fix now or you're not getting paid! :x P.S. Quote Link to comment Share on other sites More sharing options...
ReMark Posted December 18, 2008 Share Posted December 18, 2008 Slacker:lol: :lol: Lee: First. You knock these things out with such ease I'm jealous. You really seem to have a knack for lisp. Second. Do you ever sleep? Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 18, 2008 Share Posted December 18, 2008 First. You knock these things out with such ease I'm jealous. You really seem to have a knack for lisp. Thanks - I get a lot of practice on here Second. Do you ever sleep? Rarely, I must admit... Quote Link to comment Share on other sites More sharing options...
johnengineer Posted December 18, 2008 Author Share Posted December 18, 2008 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. Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 18, 2008 Share Posted December 18, 2008 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 Quote Link to comment Share on other sites More sharing options...
johnengineer Posted December 18, 2008 Author Share Posted December 18, 2008 Thanks Lee Mac. You have an exceptional ability! Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 18, 2008 Share Posted December 18, 2008 Thanks Lee Mac. You have an exceptional ability! Thanks Happy to help out. Quote Link to comment Share on other sites More sharing options...
David Bethel Posted December 19, 2008 Share Posted December 19, 2008 (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 Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 19, 2008 Share Posted December 19, 2008 David you put me to shame Just when I think I have understood LISP, I am amazed to find more to learn Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 19, 2008 Share Posted December 19, 2008 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 Quote Link to comment Share on other sites More sharing options...
David Bethel Posted December 20, 2008 Share Posted December 20, 2008 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 Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 20, 2008 Share Posted December 20, 2008 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. Quote Link to comment Share on other sites More sharing options...
CAB Posted December 22, 2008 Share Posted December 22, 2008 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) ) Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 22, 2008 Share Posted December 22, 2008 I am really impressed with your codes CAB, but of the many questions I want to ask, heres one of them: What is the difference between distof and atof? Thanks, Lee Quote Link to comment Share on other sites More sharing options...
CAB Posted December 22, 2008 Share Posted December 22, 2008 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 Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted December 22, 2008 Share Posted December 22, 2008 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 Quote Link to comment Share on other sites More sharing options...
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.