+ Reply to Thread
Results 1 to 7 of 7

Thread: Reverse Numbers

  1. #1
    Full Member benhubel's Avatar
    Computer Details
    benhubel's Computer Details
    Operating System:
    Windows 7
    Discipline
    Manufacture
    benhubel's Discipline Details
    Occupation
    Waterjet Programmer
    Discipline
    Manufacture
    Using
    AutoCAD 2012
    Join Date
    Dec 2015
    Location
    Dallas, Texas
    Posts
    76

    Default Reverse Numbers

    Registered forum members do not see this ad.

    I regularly use text to number objects for designating cut order. In the past, I have cobbled together some code that can quickly increment or decrement all selected numerical text in case I make a mistake and/or have to change something. This works marvelously, but often, I find that I need to go beyond that and completely reverse the order.

    Using this code as a starting point, I thought this would be super simple but the fact that I'm trying to do list manipulation to text objects is completely throwing me off. I'm still a bit new to this sort of thing. I was thinking I'd get a list of all selected text, sort it, then reverse that list before applying changes to the text. Highest number gets swapped with the lowest, second highest with second lowest, etc.

    ("1" "2") would become ("2" "1")
    ("2" "1" "4" "5" "3") would become ("4" "5" "2" "1" "3")
    ("2" "8" "17" "4") would become ("17" "4" "2" "8")
    ("3" "5" "-4") would become ("3" "-4" "5")

    I'm not sure where to start, nor what process to use. My main problem is that I can't figure out how to sort and edit the data without losing links to the correct text objects. Any help would be awesome. Here is the my quick increment/decrement routine that I'm trying to start with.

    Code:
    ;Quick Increment/decrement
    ;Increments/decrements all selected text integers by 1
    ;I hacked this code together with help from an "increment in range" routine.
    ;Original code can be found here https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/incriment-numbered-text/td-p/3614646?nobounce
    
    ;Quick Increment
    (defun C:qi (/ textselection textobject old)
      (vl-load-com)
      (setq textselection (ssget '((0 . "TEXT"))))
      (repeat (sslength textselection)
        (setq
          textobject (vlax-ename->vla-object (ssname textselection 0))
          old (vla-get-TextString textobject); initial text content
        ); setq
        (if
          (and
            (= (strlen old) (strlen (itoa (atoi old)))); text represents integer
              ; Blocks e.g. "12A", "4.5", "C37", and completely non-numerical
              ;   text [except for next test], but allows negative integers.
              ; Also disallows e.g. "06", "008", so if those should be included...
            (if (= (strlen old) 1) (wcmatch old "#") T)
              ; blocks single non-numerical character e.g. "A" [passes prior test]
          ); and
          (vla-put-TextString textobject (itoa (+ (atoi old) 1))); replace
        ); if
        (ssdel (ssname textselection 0) textselection)
      ); repeat
      (princ)
      (setq sel1 (ssget "P"))
      (sssetfirst nil sel1)
    ); defun
    
    ;Quick decrement
    (defun C:qd (/ textselection textobject old)
      (vl-load-com)
      (setq textselection (ssget '((0 . "TEXT"))))
      (repeat (sslength textselection)
        (setq
          textobject (vlax-ename->vla-object (ssname textselection 0))
          old (vla-get-TextString textobject); initial text content
        ); setq
        (if
          (and
            (= (strlen old) (strlen (itoa (atoi old)))); text represents integer
              ; Blocks e.g. "12A", "4.5", "C37", and completely non-numerical
              ;   text [except for next test], but allows negative integers.
              ; Also disallows e.g. "06", "008", so if those should be included...
            (if (= (strlen old) 1) (wcmatch old "#") T)
              ; blocks single non-numerical character e.g. "A" [passes prior test]
          ); and
          (vla-put-TextString textobject (itoa (- (atoi old) 1))); replace
        ); if
        (ssdel (ssname textselection 0) textselection)
      ); repeat
      (princ)
      (setq sel1 (ssget "P"))
      (sssetfirst nil sel1)
    ); defun
    I just now discovered for the first time that I am prone to memory loss.

  2. #2
    Senior Member Jef!'s Avatar
    Using
    AutoCAD 2008
    Join Date
    Sep 2010
    Posts
    233

    Default

    Hi Benhubel. Here's few thougths

    To sort strings, you could use the acad_strlsort function. The downside is that it will classify them using ascii values.
    Code:
    (acad_strlsort '("4" "5" "2" "1" "3" "10"))
    ("1" "10" "2" "3" "4" "5")
    If all the numbers you have are the same length, (01, 04, 12, 16), it will do the job "as is". If not you will need to manipulate things. Either you...
    -Check for the digit with the biggest strlen, and add as many 0 in front of the digits , sort them and then remove the 0's after sorting. Painfull
    -or you could retrieve the strings containing the integers, swap them to integers before creating the list to vl-sort it or
    -just leave it as is (list of strings) and use atoi on each member, to rebuild a new list...
    Code:
    (defun test ( lst / retlist)
      (foreach mem lst
        (setq retlist (cons (atoi mem) retlist))
      )
      (vl-sort retlist '<)
    )
    (test '("4" "5" "002" "1" "3" "10"))
    (1 2 3 4 5 10)
    Boom!

    Another thing I do if I need to keep a link with a said thing (lets say value and <ename>), I create a list of dotted pairs instead of a plain list. ((value1 . <ename1>)(value2 . <ename2>)(etc..)) for instance. You can then vl-sort it by the car, and when it is time to handle the information later on, you can retrieve the corresponding <ename> easily with cdr. That should be a good starting point for you.

    Hope it helps
    Cheers
    Last edited by Jef!; 1st Mar 2017 at 09:48 pm. Reason: typo fix
    Different goal also quite often means different path...

  3. #3
    Super Member
    Discipline
    Multi-disciplinary
    Using
    AutoCAD 2015
    Join Date
    Nov 2013
    Posts
    1,063

    Default

    Another thought:
    Code:
    _$ (vl-sort '("4" "3" "10" "0" "0.52" "1" "-3.4" "-0.25" "5" "2" "-2" "3.5" "6.8")
      '(lambda (a b) (apply '< (mapcar 'read (list a b))))
    )
    ("-3.4" "-2" "-0.25" "0" "0.52" "1" "2" "3" "3.5" "4" "5" "6.8" "10")
    _$

  4. #4
    Senior Member
    Discipline
    Structural
    Using
    AutoCAD 2014
    Join Date
    Sep 2011
    Location
    Baia Mare, Romania
    Posts
    375

    Default

    Quote Originally Posted by benhubel View Post
    ("1" "2") would become ("2" "1")
    ("2" "1" "4" "5" "3") would become ("4" "5" "2" "1" "3")
    ("2" "8" "17" "4") would become ("17" "4" "2" "8")
    ("3" "5" "-4") would become ("3" "-4" "5")
    Hi benhubel
    I don't know what the code you posted has anything to do with the quoted task. Here is a sample of how you could swap the min/max values in the list:
    Code:
    (defun swap (l / r n)
      (setq r (vl-sort l
                '(lambda (a b)
                   (< (atoi a) (atoi b))
                 )
              )
      )
      (setq n (1- (length l)))
      (mapcar
        '(lambda (x)
           (nth (- n x) r)
         )
        (vl-sort-i
          (vl-sort-i
            (mapcar 'atoi l)
            '<
          )
          '<
        )
      )
    )
    Code:
    _$ (swap '("1" "2")) -> ("2" "1")
    _$ (swap '("2" "1" "4" "5" "3")) -> ("4" "5" "2" "1" "3")
    _$ (swap '("2" "8" "17" "4")) -> ("17" "4" "2" "8")
    _$ (swap '("3" "5" "-4")) -> ("3" "-4" "5")
    About the number-entity association, please describe more precise what you are after.
    You can make an associated list, as suggested by Jef, but is still unclear for me.
    A list like
    Code:
    (("3" . Ent1) ("1" . Ent2) ("2" . Ent3))
    would become
    Code:
    (("1" . Ent1) ("3" . Ent2) ("2" . Ent3))
    or
    Code:
    (("1" . Ent2) ("3" . Ent1) ("2" . Ent3))
    Note Ent1 and Ent2 initial and final position.

  5. #5
    Full Member benhubel's Avatar
    Computer Details
    benhubel's Computer Details
    Operating System:
    Windows 7
    Discipline
    Manufacture
    benhubel's Discipline Details
    Occupation
    Waterjet Programmer
    Discipline
    Manufacture
    Using
    AutoCAD 2012
    Join Date
    Dec 2015
    Location
    Dallas, Texas
    Posts
    76

    Default

    Thank you for the replies.

    The code I quoted is my starting point for dealing with the text objects. I'm aiming for the finished program to work the same as code I posted, except that instead of incrementing the numbers, it reverses them.
    I will experiment with the examples you guys gave and see what I can build. It looks like the associated list will probably be the way to go if I'm able to make it work correctly.

    Just for clarity, this image is an example of what I am attempting to do.
    Attached Images
    I just now discovered for the first time that I am prone to memory loss.

  6. #6
    Senior Member
    Discipline
    Structural
    Using
    AutoCAD 2014
    Join Date
    Sep 2011
    Location
    Baia Mare, Romania
    Posts
    375

    Default

    Not necessary a assoc list. In fact, it is more easy in this case with 2 different lists.
    Code:
    (defun c:qr ( / ss i e s obj num n u m)
      (if
        (setq ss (ssget "_:L" '((0 . "TEXT"))))
        (progn
          (repeat (setq i (sslength ss))
            (setq e (vlax-ename->vla-object (ssname ss (setq i (1- i))))
                  s (vla-get-textstring e)
            )
            (if
              (and (setq d (distof s)) (equal d (fix d) 1e-8))
              (setq obj (cons e obj)
                    num (cons (atoi s) num)
              )
            )
          )
          (if num
            (progn
              (setq n (vl-sort-i num '<)
                    u (mapcar '(lambda (x) (nth x num)) n)
                    m (1- (length num))
              )
              (mapcar
                '(lambda (e x)
                   (vla-put-textstring e (itoa (nth (- m x) u)))
                 )
                obj
                (vl-sort-i n '<)
              )
            )
          )
        )
      )
      (princ)
    )
    Works with duplicates, but the result is unpredictable (I guess it shouldn't be any duplicate).

  7. #7
    Full Member benhubel's Avatar
    Computer Details
    benhubel's Computer Details
    Operating System:
    Windows 7
    Discipline
    Manufacture
    benhubel's Discipline Details
    Occupation
    Waterjet Programmer
    Discipline
    Manufacture
    Using
    AutoCAD 2012
    Join Date
    Dec 2015
    Location
    Dallas, Texas
    Posts
    76

    Default

    Registered forum members do not see this ad.

    Woah, that works great! I'll have to look it over and see if I can understand everything that's going on in it. Thank you very much!
    I just now discovered for the first time that I am prone to memory loss.

Similar Threads

  1. Convert integers numbers into real numbers, introducing decimal separator.
    By teknomatika in forum AutoLISP, Visual LISP & DCL
    Replies: 8
    Last Post: 3rd Sep 2010, 04:07 pm
  2. Reverse Engineering
    By harley558 in forum Autodesk Inventor
    Replies: 1
    Last Post: 23rd Jul 2010, 05:51 pm
  3. Drawing in reverse
    By YachtyKev in forum Autodesk Inventor
    Replies: 3
    Last Post: 22nd Jan 2010, 03:33 am
  4. Reverse DIM exploding
    By Cad Sponge in forum AutoCAD Drawing Management & Output
    Replies: 3
    Last Post: 11th Oct 2007, 11:21 pm
  5. adding numbers to numbers
    By philk in forum AutoLISP, Visual LISP & DCL
    Replies: 4
    Last Post: 23rd Feb 2006, 05:45 pm

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts