Author Topic: Reverse a string of text  (Read 6404 times)

0 Members and 1 Guest are viewing this topic.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Reverse a string of text
« Reply #15 on: February 01, 2011, 07:37:07 PM »
Very slick Lee. 8-)

This is the long way. :-)
Code: [Select]
(defun c:numFirst (/ ss i ename txt str elst nlst nstr)
  ;;  parser by CAB  
  (defun sparser (str delim / ptr lst)
    (while (setq ptr (vl-string-search delim str))
      (setq lst (cons (substr str 1 ptr) lst))
      (setq str (substr str (+ ptr 2)))
    )
    (reverse (cons str lst))
  )

  (defun chkStr (s / num str)
    (if (wcmatch s "*#")
      (progn
        (mapcar
          (function
            (lambda (x)
              (if (< 47 x 58)
                (setq num (cons x num))
                (setq str (cons x str))
              )
            )
          )
          (reverse (vl-string->list S))
        )
        (vl-list->string (if str (append num str) num))
      )
      s
    )
  )

  (if (setq ss (ssget "_:L" '((0 . "TEXT"))))
    (progn
      (setq i -1)
      (while (setq ename (ssname ss (setq i (1+ i))))
        (setq nstr nil
              nlst nil)
        (setq txt (cdr (assoc 1 (setq elst (entget ename)))))
        (foreach str (setq lst (sparser txt " "))
          (setq str (chkStr str))
          (setq nlst (cons str nlst))
        )
        (mapcar (function (lambda(s) (setq nstr (if nstr (strcat nstr " " s) s)))) (reverse nlst))
        (if nstr (entmod (subst (cons 1 nstr) (assoc 1 elst) elst)))
      )
    )
  )

  (princ)
)

edit: Added "_:L" to my ssget, thanks for the reminder Lee
« Last Edit: February 02, 2011, 08:13:20 AM by CAB »
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: 12914
  • London, England
Re: Reverse a string of text
« Reply #16 on: February 01, 2011, 07:57:23 PM »
Thanks Alan, nice code also  :-)

I should probably include a more appropriate calling function for mine:

Code: [Select]
(defun c:test ( / RegEx ss i str elist ) (vl-load-com)

  (setq RegEx  (vlax-get-or-create-object "VBScript.RegExp"))

  (mapcar
    (function
      (lambda ( x ) (vlax-put-property regex (car x) (cdr x)))
    )
    (list
      (cons 'global      acfalse)
      (cons 'ignorecase  actrue)
      (cons 'multiline   acfalse)
      (cons 'pattern     "([A-Z]+)(\\d+)\\b")
    )
  )

  (if (setq ss (ssget "_:L" '((0 . "TEXT") (1 . "*@#*"))))
   
    (repeat (setq i (sslength ss))
      (setq str (cdr (assoc 1 (setq elist (entget (ssname ss (setq i (1- i))))))))

      (if (not (eq str (setq str (vlax-invoke regex 'replace str "$2$1"))))
        (entupd (cdr (assoc -1 (entmod (subst (cons 1 str) (assoc 1 elist) elist)))))
      )
    )
  )

  (vlax-release-object RegEx)
  (princ)
)

EDIT: In fact, I think it'd be more efficient without the sub :-)

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Reverse a string of text
« Reply #17 on: February 02, 2011, 05:55:02 AM »
my variant, not use vla:
Code: [Select]
(defun f (l)
 (cond ((= (caddr l) "") (strcat (cadr l) (car l)))
       ((wcmatch (caddr l) "@*") (f (list (strcat (car l) (substr (caddr l) 1 1)) (cadr l) (substr (caddr l) 2))))
       ((wcmatch (caddr l) "#*") (f (list (car l) (strcat (cadr l) (substr (caddr l) 1 1)) (substr (caddr l) 2))))
       ((strcat (cadr l) (car l) " " (f (list "" "" (substr (caddr l) 2)))))
 )
)

Test function:
Code: [Select]
(defun c:test (/ s)
 (setq s "FUSE A7 2A 24VDC")
 (f (list "" "" s))
)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Reverse a string of text
« Reply #18 on: February 02, 2011, 08:04:02 AM »
Evgeniy,

Nice idea to separate the alpha/numerical sections into separate elements of the list (I wouldn't have thought to approach it in that way...) - I should imagine you lose performance however with the recursion combined with the inefficient strcat/substr functions...

The trace call is quite elegant:

Code: [Select]
Entering (F ("" "" "FUSE A7 2A 24VDC"))
  Entering (F ("F" "" "USE A7 2A 24VDC"))
    Entering (F ("FU" "" "SE A7 2A 24VDC"))
      Entering (F ("FUS" "" "E A7 2A 24VDC"))
        Entering (F ("FUSE" "" " A7 2A 24VDC"))
          Entering (F ("" "" "A7 2A 24VDC"))
            Entering (F ("A" "" "7 2A 24VDC"))
              Entering (F ("A" "7" " 2A 24VDC"))
                Entering (F ("" "" "2A 24VDC"))
                  Entering (F ("" "2" "A 24VDC"))
                    Entering (F ("A" "2" " 24VDC"))
                      Entering (F ("" "" "24VDC"))
                        Entering (F ("" "2" "4VDC"))
                          Entering (F ("" "24" "VDC"))
                            Entering (F ("V" "24" "DC"))
                              Entering (F ("VD" "24" "C"))
                                Entering (F ("VDC" "24" ""))
                                Result:  "24VDC"
                              Result:  "24VDC"
                            Result:  "24VDC"
                          Result:  "24VDC"
                        Result:  "24VDC"
                      Result:  "24VDC"
                    Result:  "2A 24VDC"
                  Result:  "2A 24VDC"
                Result:  "2A 24VDC"
              Result:  "7A 2A 24VDC"
            Result:  "7A 2A 24VDC"
          Result:  "7A 2A 24VDC"
        Result:  "FUSE 7A 2A 24VDC"
      Result:  "FUSE 7A 2A 24VDC"
    Result:  "FUSE 7A 2A 24VDC"
  Result:  "FUSE 7A 2A 24VDC"
Result:  "FUSE 7A 2A 24VDC"

However, you will have a problem with:

Code: [Select]
(setq s "FUSE A10A")
A possible fix might be:

Code: [Select]
(defun f ( l )
  (cond
    ( (= (caddr l) "")

      (strcat (cadr l) (car l))
    )
    ( (and (< 0 (strlen (cadr l))) (wcmatch (caddr l) "@*"))

      (f (list (strcat (car l) (cadr l) (substr (caddr l) 1 1)) "" (substr (caddr l) 2)))
    )
    ( (wcmatch (caddr l) "@*")

      (f (list (strcat (car l) (substr (caddr l) 1 1)) (cadr l) (substr (caddr l) 2)))
    )
    ( (wcmatch (caddr l) "#*")

      (f (list (car l) (strcat (cadr l) (substr (caddr l) 1 1)) (substr (caddr l) 2)))
    )
    ( (strcat (cadr l) (car l) " " (f (list "" "" (substr (caddr l) 2))))
    )
  )
)

:-)
« Last Edit: February 02, 2011, 08:07:32 AM by Lee Mac »

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Reverse a string of text
« Reply #19 on: February 02, 2011, 08:24:46 AM »
Thanks Lee!  :-)
Thanks for the correction.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Reverse a string of text
« Reply #20 on: February 02, 2011, 09:04:07 AM »
Mine would choke on this FUSE F10-A30 -> FUSE F10-30A

But that was not in the requirements.  :evil:
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: 12914
  • London, England
Re: Reverse a string of text
« Reply #21 on: February 02, 2011, 09:17:44 AM »
This might be a better pattern to match:

Code: [Select]
(defun c:test ( / RegEx ss i str elist ) (vl-load-com)

  (setq RegEx  (vlax-get-or-create-object "VBScript.RegExp"))

  (mapcar
    (function
      (lambda ( x ) (vlax-put-property regex (car x) (cdr x)))
    )
    (list
      (cons 'global      actrue)
      (cons 'ignorecase  actrue)
      (cons 'multiline   acfalse)
      (cons 'pattern     "([A-Z]+)(\\d+)(\\s|$)")
    )
  )

  (if (setq ss (ssget "_:L" '((0 . "TEXT") (1 . "*@#*"))))
   
    (repeat (setq i (sslength ss))
      (setq str (cdr (assoc 1 (setq elist (entget (ssname ss (setq i (1- i))))))))

      (if (not (eq str (setq str (vlax-invoke regex 'replace str "$2$1$3"))))
        (entupd (cdr (assoc -1 (entmod (subst (cons 1 str) (assoc 1 elist) elist)))))
      )
    )
  )

  (vlax-release-object RegEx)
  (princ)
)

Note sure if the 'global' property is required or not, but that is an easy switch in the code.

Code: [Select]
FUSE A2 A10A F10-A30  -->  FUSE 2A A10A F10-30A

FUSE A12 1A 12VDC     -->  FUSE 12A 1A 12VDC

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Reverse a string of text
« Reply #22 on: February 02, 2011, 09:55:56 AM »
Very controversial mechanism:
Code: [Select]
"FUSE A2 A10A A10-A30" -->> "FUSE 2A A10A A10-30A"

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Reverse a string of text
« Reply #23 on: February 02, 2011, 09:58:18 AM »
Very controversial mechanism:
Code: [Select]
"FUSE A2 A10A A10-A30" -->> "FUSE 2A A10A A10-30A"

True, it wasn't in the OP's requirements, but we like to go the extra mile  ;-)

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Reverse a string of text
« Reply #24 on: February 02, 2011, 10:03:23 AM »
my variant 2:
Code: [Select]
(defun f (l)
 (cond ((= (caddr l) "") (strcat (cadr l) (car l)))
       ((wcmatch (caddr l) "@*") (f (list (strcat (car l) (cadr l) (substr (caddr l) 1 1)) "" (substr (caddr l) 2))))
       ((wcmatch (caddr l) "#*") (f (list (car l) (strcat (cadr l) (substr (caddr l) 1 1)) (substr (caddr l) 2))))
       ((strcat (cadr l) (car l) (substr (caddr l) 1 1) (f (list "" "" (substr (caddr l) 2)))))
 )
)

Code: [Select]
(f '("""""FUSE A2 A10A F10-A30")) ;;  -->  "FUSE 2A A10A 10F-30A"
:)