TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: ronjonp on March 28, 2006, 10:49:44 AM
-
I'm gathering all the layers in a drawing and want to convert the names of xref layers from: dwg|nesteddwg|layname to *|layname. What would be the easiest way to accomplish this?
Thanks,
Ron
-
Ron, if the XREFs have been bound and exploded, you could try this routine:
;REMVLONG.lsp
;
;OBJECTIVE***
;The purpose of this routine is to allow the user to strip
;the lengthy portion of layer name including the "|0|" which
;result from the binding of external reference files.
;
;SPECIAL INSTRUCTIONS***
;1. Explode all Bound External Reference Files before beginning.
;2. Due to the nature of this routine, it should be understood
;that the layers are not renamed, therefore, the layer name
;remains. To remove it, you must DXFOUT your file, recreate
;the file from the DXF and then purge to rid the layers, blocks,
;and linetypes.
;
(Defun c:REMVLONG ()
(prompt "\nRoutine to remove Bound Layer Names")
(command "undo" "m")
(setq c_lyr (getvar "CLAYER"))
(COLLECT_DATA)
)
(Defun COLLECT_DATA ()
(setq lyrs (tblnext "LAYER" T))
(while (/= lyrs nil)
(setq lyr_nam (cdr (assoc 2 lyrs)))
(setq lyr_lt (cdr (assoc 6 lyrs)))
(setq lyr_clr (cdr (assoc 62 lyrs)))
(if (= (wcmatch lyr_nam "*$?$*") T)
(progn
(setq ss_dat (ssget "X" (list (cons 8 lyr_nam))))
(EVAL_LYR)
(EVAL_LT)
(if (= (tblsearch "LAYER" lyr) nil)
(progn
(if (= (wcmatch lyr_lt "*$?$*") T)
(command "layer" "m" lyr "c" lyr_clr "" "lt" lt "" "")
(command "layer" "m" lyr "c" lyr_clr "" "lt" lyr_lt "" "")
)
)
)
(if (/= ss_dat nil)
(command "change" ss_dat "" "p" "la" lyr "")
)
)
)
(setq lyrs (tblnext "LAYER"))
)
(setvar "CLAYER" c_lyr)
(if (= (substr (getvar "acadver") 1 2) "13")
(repeat 3
(command "purge" "b" )
(while (= (getvar "CMDNAMES") "PURGE")
(command "y" )
);end while
)
)
)
(Defun EVAL_LYR ()
(if (= (wcmatch lyr_nam "*$?$*") T)
(progn
(setq
nam_len (strlen lyr_nam)
cnt 1
fnd (substr lyr_nam cnt 3)
fndit (wcmatch fnd "$?$")
)
(while (/= fndit T)
(setq
cnt (+ 1 cnt)
fnd (substr lyr_nam cnt 3)
fndit (wcmatch fnd "$?$")
)
)
(setq lyr (substr lyr_nam (+ cnt 3)))
)
)
)
(Defun EVAL_LT ()
(if (= (wcmatch lyr_lt "*$?$*") T)
(progn
(setq
lt_len (strlen lyr_lt)
cnt 1
fnd (substr lyr_lt cnt 3)
fndit (wcmatch fnd "$?$")
)
(while (/= fndit T)
(setq
cnt (+ 1 cnt)
fnd (substr lyr_lt cnt 3)
fndit (wcmatch fnd "$?$")
)
)
(setq lt (substr lyr_lt (+ cnt 3)))
(setq is_lt (ssget "X" (list (cons 6 lyr_lt))))
(if (= is_lt nil)
(progn
(command "filedia" "0")
(command "linetype" "l" lt "" "" "")
(command "filedia" "1")
)
)
)
)
)
(prompt "\nCommand Name is Remvlong\n")
-
Thanks for the reply Slim....I'll try and digest what you've posted :).
-
Have you tried the RENAME command?
-
The RENAME command works well too, it uses wildcards & such.
-
OK...so I've taken this as a learning experience and wanted to try my hand at a function......this is what I came up with:
(defun striptext (lyr_nam / pstn X)
(if (= (wcmatch lyr_nam "*|*") T)
(progn
(setq X T)
(while (= X T)
(setq
pstn (+ (vl-string-position (ascii "|") lyr_nam) 2)
lyr_nam (substr lyr_nam pstn)
)
(if (= (wcmatch lyr_nam "*|*") T)
(setq X T)
(setq X nil)
)
)
lyr_nam
)
)
)
(striptext "123|456|789")
"789"
Any suggestions?
Thanks,
Ron
-
Written and posted for fun --
(defun StripXrefPrefix ( string )
( (lambda ( position )
(if position
(substr string (+ 2 position))
string
)
)
(vl-string-position 124 string 0 t)
)
)
:)
-
Written and posted for fun --
(defun StripXrefPrefix ( string )
( (lambda ( position )
(if position
(substr string (+ 2 position))
string
)
)
(vl-string-position 124 string 0 t)
)
)
:)
Show off :-D just kidding....you make it look so easy.
-
Show off :-D just kidding....you make it look so easy.
Just trying to get you to look at the problem / solution another way .. and have some fun at the same time .. honest.
If you find the lambda stuff annoying here's a lambdaless equivalent --
(defun StripXrefPrefix ( string / position )
(if (setq position (vl-string-position 124 string 0 t))
(substr string (+ 2 position))
string
)
)
:)
-
Doesn't he though. :-)
Here with lists:
(defun stripxrefprefix (string / result lst)
(setq result (vl-string->list string))
(while (setq lst (cdr (member (ascii "|") result)))
(setq result lst)
)
(vl-list->string result)
)
-
Thanks for the examples :). You know it took me two hours to write mine? :oops::pissed:
-
Thanks for the examples :). You know it took me two hours to write mine? :oops::pissed:
♪ Fret not, we all start from the same point ♪
:)
-
Here is my recursive approach.
(defun StripString (String Delim / Pos)
(if (setq Pos (vl-string-search Delim String))
(StripString (substr String (1+ (+ Pos (strlen Delim)))) Delim)
String
)
)
Command: (StripString "123|456|768|596" "|")
"596"
-
For fun I benched all the variants --
Using testString = "123" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPXREFPREFIX TESTSTRING)......1156 / 1.05 <fastest>
(TW_STRIPSTRING TESTSTRING "|")......1203 / 1.01
(RP_STRIPTEXT TESTSTRING)............1218 / 1.00
(CAB_STRIPXREFPREFIX TESTSTRING).....1219 / 1.00 <slowest>
Using testString = "123|456" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPXREFPREFIX TESTSTRING)......1265 / 1.14 <fastest>
(CAB_STRIPXREFPREFIX TESTSTRING).....1313 / 1.10
(RP_STRIPTEXT TESTSTRING)............1359 / 1.06
(TW_STRIPSTRING TESTSTRING "|")......1438 / 1.00 <slowest>
Using testString = "123|456|789" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPXREFPREFIX TESTSTRING)......1266 / 1.15 <fastest>
(CAB_STRIPXREFPREFIX TESTSTRING).....1359 / 1.07
(RP_STRIPTEXT TESTSTRING)............1438 / 1.01
(TW_STRIPSTRING TESTSTRING "|")......1453 / 1.00 <slowest>
Using testString = "123|456|789|ABC" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPXREFPREFIX TESTSTRING)......1266 / 1.21 <fastest>
(CAB_STRIPXREFPREFIX TESTSTRING).....1390 / 1.10
(RP_STRIPTEXT TESTSTRING)............1515 / 1.01
(TW_STRIPSTRING TESTSTRING "|")......1531 / 1.00 <slowest>
Using testString = "123|456|789|ABC|DEF" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPXREFPREFIX TESTSTRING)......1281 / 1.28 <fastest>
(CAB_STRIPXREFPREFIX TESTSTRING).....1437 / 1.14
(RP_STRIPTEXT TESTSTRING)............1594 / 1.03
(TW_STRIPSTRING TESTSTRING "|")......1640 / 1.00 <slowest>
Using testString = "123|456|789|ABC|DEF|GHI|JKL|MNO|PQR" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPXREFPREFIX TESTSTRING)......1265 / 1.57 <fastest>
(CAB_STRIPXREFPREFIX TESTSTRING).....1734 / 1.14
(RP_STRIPTEXT TESTSTRING)............1906 / 1.04
(TW_STRIPSTRING TESTSTRING "|")......1984 / 1.00 <slowest>
Here's the bench code --
( (lambda
(
/
TW_StripString
CAB_stripxrefprefix
MP_StripXrefPrefix
RP_StripText
)
(defun TW_StripString (String Delim / Pos)
(if (setq Pos (vl-string-search Delim String))
(TW_StripString
(substr String (1+ (+ Pos (strlen Delim))))
Delim
)
String
)
)
(defun CAB_stripxrefprefix (string / result lst)
(setq result (vl-string->list string))
(while (setq lst (cdr (member (ascii "|") result)))
(setq result lst)
)
(vl-list->string result)
)
(defun MP_StripXrefPrefix ( string / position )
(if (setq position (vl-string-position 124 string 0 t))
(substr string (+ 2 position))
string
)
)
(defun RP_StripText (lyr_nam / pstn X)
(if (= (wcmatch lyr_nam "*|*") T)
(progn
(setq X T)
(while (= X T)
(setq
pstn (+ (vl-string-position (ascii "|") lyr_nam) 2)
lyr_nam (substr lyr_nam pstn)
)
(if (= (wcmatch lyr_nam "*|*") T)
(setq X T)
(setq X nil)
)
)
lyr_nam
)
)
)
;;
;; main
;;
(foreach testString
'( "123"
"123|456"
"123|456|789"
"123|456|789|ABC"
"123|456|789|ABC|DEF"
"123|456|789|ABC|DEF|GHI|JKL|MNO|PQR"
)
(princ (strcat "\nUsing testString = \"" testString "\" ...\n\n"))
(BenchMark
'(
(TW_StripString testString "|")
(CAB_stripxrefprefix testString)
(MP_StripXrefPrefix testString)
(RP_StripText testString)
)
)
)
)
)
PS -- RonJonP -- you may wish to examine your function's result when it is passed a string that doesn't host the dilimiter, e.g. "123".
Cheers.
Michael.
-
I found that one out. My workaround was to enclose my function in an if statement.
Someday I'll write pretty code.
-
For fun I benched all the variants --
Woooowhoooooo!!!
Mine was the slowest, but it was still something I just learned, so I thought it would be fun to post it.
Is this typical of recursive programs? or was this a bad example? Sorry for the thread hijacking.. :cry:
-
Edit: Fixed typo in MP_StripPrefixRecEx.
As I noted in another thread, recursive functions typically represent convenience for the programmer, but more work for the computer.
Optimizing recursive functions is a big topic Tim, and not one I'm particularly qualified to author, but I would say that when writing recursive functions some of the things you have to do are eliminate redundant function calls and variable declarations.
For example -- pretending that vl-string-position doesn't have the optional "start from the end" argument let's write a recursive variant that employs a common technique: write core (recursive) functionality as a function that is initially invoked via a wrapper --
(defun MP_StripPrefixRecEx ( string code )
;; Not to be called directly, only via wrapper
;; function MP_StripPrefixRec.
;;
;; Uses argument 'code' which is calculated
;; using the ascii function only once, by the
;; calling / parent code.
;;
;; Uses global scope variable 'position' declared
;; by the calling code (or fully global if the
;; parent code does not declare said variable),
;; so it doen't have to push more onto the stack
;; with each successive iteration than is absolutely
;; esssential.
(if (setq position (vl-string-position code string))
(MP_StripPrefixRecEx
(substr string (+ 2 position))
code
)
String
)
)
(defun MP_StripPrefixRec ( string delim / position )
;; I am the wrapper code, responsible for doing any
;; preprocessing, e.g. the (ascii delim) call as well
;; as declaring any variables that are used in the
;; MP_StripPrefixRecEx function, like the 'position'
;; variable.
;;
;; Generally speaking this is bad, bad coding practice as
;; it requires one function to have intimate knowledge
;; of the inner workings of another function, breaking
;; black box rules and making for all kinds of potential
;; maintenance woes. In this case I'm saying "it's ok"
;; because this function is written entirely in the
;; context of the other -- the two work together.
(MP_StripPrefixRecEx string (ascii delim))
)
Having spent the time to optimize a little bit, the actual benefits may not be realized until the recurse levels get a little deep, as the following illuminates --
Using testString = "123" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(TW_STRIPSTRING TESTSTRING "|")........1281 / 1.04 <fastest>
(MP_STRIPPREFIXREC TESTSTRING "|").....1328 / 1.00 <slowest>
Using testString = "123|456" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPPREFIXREC TESTSTRING "|").....1469 / 1.02 <fastest>
(TW_STRIPSTRING TESTSTRING "|")........1500 / 1.00 <slowest>
Using testString = "123|456|789" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPPREFIXREC TESTSTRING "|").....1562 / 1.02 <fastest>
(TW_STRIPSTRING TESTSTRING "|")........1593 / 1.00 <slowest>
Using testString = "123|456|789|ABC" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPPREFIXREC TESTSTRING "|").....1562 / 1.06 <fastest>
(TW_STRIPSTRING TESTSTRING "|")........1656 / 1.00 <slowest>
Using testString = "123|456|789|ABC|DEF" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPPREFIXREC TESTSTRING "|").....1593 / 1.12 <fastest>
(TW_STRIPSTRING TESTSTRING "|")........1781 / 1.00 <slowest>
Using testString = "123|456|789|ABC|DEF|GHI|JKL|MNO|PQR" ...
Elapsed milliseconds / relative speed for 32768 iteration(s):
(MP_STRIPPREFIXREC TESTSTRING "|").....1781 / 1.18 <fastest>
(TW_STRIPSTRING TESTSTRING "|")........2093 / 1.00 <slowest>
Sorry, that's all I've got for now.
-
Thanks Michael. Something (more) to study.
-
Sorry for the thread hijacking.. :cry:
Normal around here...
Ron, did you get the help you needed? :-)
-
Oops, <big> sorry Ron.
(http://www.theswamp.org/screens/mp/blush.gif)
-
Sorry for the thread hijacking.. :cry:
Normal around here...
Ron, did you get the help you needed? :-)
I got all the help I needed and more....par usual. Thanks guys :)
-
Show off :-D just kidding....you make it look so easy.
Just trying to get you to look at the problem / solution another way .. and have some fun at the same time .. honest.
If you find the lambda stuff annoying here's a lambdaless equivalent --
(defun StripXrefPrefix ( string / position )
(if (setq position (vl-string-position 124 string 0 t))
(substr string (+ 2 position))
string
)
)
:)
MP,
How could this be modified to strip the string down to thesecond to last bar -->>
ABC|123|456|789 to 456|789
Thanks,
Ron
-
Not sure I understand. Could you please show original data and desired data, for example --
Original: "ABC|123|456|789 to 456|789"
Desired: "789 to 456|789"
Thanks.
:)
-
MP,
Does this help?
Original: "ABC|123|456|789"
Desired: "456|789
Original: "098|ABC|123|456|789"
Desired: "456|789
Instead of stripping out all of the "|" it leaves the last one and the text up to the second to last.
Thanks,
Ron
-
Edit: Simplified / renamed functions, re-ordered post to make comparison easier to discern.
Apologies -- written very quick, very dirty.
I don't really know what to call these functions but figured the candidates are better than foo1 and foo2.
Nonetheless, observe --
(defun KeepNthPlus ( n string delim / i code indexes )
;; n used in same context as nth function
;; delim is a one character string
(setq i 0 code (ascii delim))
(while (setq i (vl-string-position code string i))
(setq indexes (cons (setq i (1+ i)) indexes))
)
(cond
( (null indexes) nil)
( (< n (length indexes))
(substr string (1+ (nth n (reverse indexes))))
)
)
)
Versus --
(defun KeepReversedNthPlus ( n string delim / i code indexes )
;; n used in same context as nth function
;; but counting from the end forwards
;; delim is a one character string
(setq i 0 code (ascii delim))
(while (setq i (vl-string-position code string i))
(setq indexes (cons (setq i (1+ i)) indexes))
)
(cond
( (null indexes) nil)
( (< n (length indexes))
(substr string (1+ (nth n indexes)))
)
( string )
)
)
Set up some test data --
(setq testString "abc|def|ghi|jkl|mno")
Test KeepNthPlus --
(foreach i '(0 1 2 3 4)
(princ
(strcat
"(KeepNthPlus "
(itoa i)
" \""
testString
"\" \"|\") => "
(vl-prin1-to-string
(KeepNthPlus i testString "|")
)
"\n"
)
)
(princ)
)
Test KeepReversedNthPlus --
(foreach i '(0 1 2 3 4)
(princ
(strcat
"(KeepReversedNthPlus "
(itoa i)
" \""
testString
"\" \"|\") => "
(vl-prin1-to-string
(KeepReversedNthPlus i testString "|")
)
"\n"
)
)
(princ)
)
Test KeepNthPlus results --
(KeepNthPlus 0 "abc|def|ghi|jkl|mno" "|") => "def|ghi|jkl|mno"
(KeepNthPlus 1 "abc|def|ghi|jkl|mno" "|") => "ghi|jkl|mno"
(KeepNthPlus 2 "abc|def|ghi|jkl|mno" "|") => "jkl|mno"
(KeepNthPlus 3 "abc|def|ghi|jkl|mno" "|") => "mno"
(KeepNthPlus 4 "abc|def|ghi|jkl|mno" "|") => nil
Test KeepReversedNthPlus results --
(KeepReversedNthPlus 0 "abc|def|ghi|jkl|mno" "|") => "mno"
(KeepReversedNthPlus 1 "abc|def|ghi|jkl|mno" "|") => "jkl|mno"
(KeepReversedNthPlus 2 "abc|def|ghi|jkl|mno" "|") => "ghi|jkl|mno"
(KeepReversedNthPlus 3 "abc|def|ghi|jkl|mno" "|") => "def|ghi|jkl|mno"
(KeepReversedNthPlus 4 "abc|def|ghi|jkl|mno" "|") => "abc|def|ghi|jkl|mno"
Something to toy with, cheers.
-
MP,
Your knowledge of writing code never ceases to amaze me. Whether it be simple or complicated you always find an elegant way to solve a problem :). This is exactly what I was looking for.
Thanks again,
Ron
-
Awefully nice of you to say Ron, that is the illusion I'm shooting for -- Thanks!
:lol:
-
Awefully nice of you to say Ron, that is the illusion I'm shooting for -- Thanks!
:lol:
:-)