Author Topic: Page Number String From List  (Read 3596 times)

0 Members and 1 Guest are viewing this topic.

cmwade77

  • Swamp Rat
  • Posts: 1443
Page Number String From List
« on: October 21, 2021, 02:49:45 PM »
So, I have a list of numbers that I would like to convert to strings, Examples would be:
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
would Return: 1-23

(1 2 3 4 5 6 11 13 14 15 16 17 18 19 20 21 22 23)
would Return: 1-6, 11, 13-23

(1 3 5 6)
would Return: 1, 3, 5, 6

I am sure I am missing something obvious in my code below, as all I am presently getting returned is the number 1, can someone please help me out?

And massive kudos if you can reverse the process, say someone enters 1-6, 11, 13-23 it would then return the list of numbers (1 2 3 4 5 6 11 13 14 15 16 17 18 19 20 21 22 23)


Code: [Select]
(defun PageNumbers->String (PageNumberList / Num str LowNumber HighNumber LastNumber Difference PartialStr)
    ;Returns string representing page numbers in list
    (setq LowNumber (car PageNumberList)
          LastNumber LowNumber
          str (rtos LowNumber 2 0)
    )
    (foreach Num (cdr PageNumberList)
      (if (or (= LowNumber nil) (= LastNumber nil))
        (progn
          (setq LowNumber Num
                LastNumber LowNumber
          )
        )
      )
      (setq Difference (- Num LastNumber)
            LastNumber Num
      );setq
      (if (< Difference 0)
        (setq Difference (* Difference -1))
      );if
      (if (<= Difference 1)
        (progn
          (setq HighNumber Num
                LastNumber HighNumber
          )
        )
        (progn
          (if (not HighNumber)
            (progn
              (if (not str)
                (setq str (strcat (rtos LowNumber 2 0)))
                (setq str (strcat str ", " (rtos LowNumber 2 0)))
              )             
              (setq LowNumber Num
                    LastNumber LowNumber
              )
            )
            (progn
              (if (not str)
                (setq str (strcat (rtos HighNumber 2 0)))
                (setq str (strcat str "-" (rtos HighNumber 2 0)))
              )
              (setq LowNumber nil
                    HighNumber nil
                    LastNumber nil
              )
            )
          )
        )
      );if
    )
    str
  )

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Page Number String From List
« Reply #1 on: October 21, 2021, 05:20:48 PM »
Ok, I got the first half of this sorted, I figured out how to get the page numbers into a properly formatted string:
Code: [Select]
(defun PageNumbers->String (PageNumberList / Numbers LastNumber Difference str LowNumber)
    ;This routine returns page numbers in a formatted list, i.e. 1-6, 10-12, 13, 15
   
    ; Sort List
    (defun JR:Sort (lst func)
    ;Code from derryck  - https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/sort-list-rational-numbers/m-p/9366406/highlight/true#M396997
      (mapcar '(lambda (x) (nth x lst)) (vl-sort-i lst func))
    )
    (setq Numbers (JR:Sort PageNumberList '<))
    (princ Numbers)
    (foreach Num Numbers
      (if (not LowNumber)
        (if (not LastNumber)
          (progn
            (setq LowNumber Num
                  LastNumber LowNumber
            );setq
          )
          (progn
            (setq LowNumber LastNumber)
          )
        )
      );if
      (if (not LastNumber)
        (setq LastNumber Num)
        (progn   
          (setq Difference (- Num LastNumber))
          (if (or (> Difference 1) (= Num (last Numbers)))
            (progn
              (if (= Num (last Numbers))
                (progn
                  (if (= str nil)
                    (progn
                      (if (/= LowNumber Num)
                        (setq str (strcat (rtos LowNumber 2 0) "-" (rtos Num 2 0)))
                        (setq str (rtos Num 2 0))
                      );if
                    );progn
                    (progn
                      (if (/= LowNumber Num)
                        (setq str (strcat str ", " (rtos LowNumber 2 0) "-" (rtos Num 2 0)))
                        (setq str (strcat str ", " (rtos Num 2 0)))
                      );if
                    );progn
                  );if
                );progn
                (progn
                  (if (= str nil)
                    (progn
                      (if (/= LowNumber Num)
                        (setq str (strcat (rtos LowNumber 2 0) "-" (rtos LastNumber 2 0)))
                        (setq str (rtos Num 2 0))
                      );if
                    );progn
                    (progn
                      (if (/= LowNumber Num)
                        (setq str (strcat str ", " (rtos LowNumber 2 0) "-" (rtos LastNumber 2 0)))
                        (setq str (strcat str ", " (rtos Num 2 0)))
                      );if
                    );progn
                  );if
                );progn
              );if
              (setq LowNumber nil)
            );progn
          );if
        );progn
      );if
      (setq LastNumber Num)   
    );foreach
    str
  );defun

Now I just need to sort out turning the string into a list.

mhupp

  • Bull Frog
  • Posts: 250
Re: Page Number String From List
« Reply #2 on: October 21, 2021, 05:35:31 PM »
Did it a little bit different. Doesn't work 100% like yours with the last example. need to tweak the logic a bit.

(P#2S '(1 2 3 4 5 6 11 13 14 15 16 17 18 19 20 21 22 23))
"1-6,11,13-23"

(P#2S '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23))
"1-23"

(P#2S '(1 3 5 6))
"1,3,5-6"

Code: [Select]
(defun PN2S (lst / n i a l rng shtlst)
  (setq lst (vl-sort lst '<))
  (while (/= lst nil)
    (setq a nil)
    (setq i 1)
    (setq n (car lst))
    (while (= a nil)
      (if (and (> (length lst) 1) (= n (- (cadr lst) i)))
        (progn
          (setq l (cadr lst))
          (setq lst (vl-remove (nth 1 lst) lst))
          (setq i (1+ i))
        )
        (progn
          (setq a "stop")
          (if (< n l)
            (setq rng (strcat (rtos n 2 0) "-" (rtos l 2 0)))
            (setq rng (strcat (rtos n 2 0)))
          )
          (setq shtlst (cons rng shtlst))
          (setq lst (vl-remove (nth 0 lst) lst))
        )
      )
    )
  )
  (setq shtlst (reverse shtlst))
  (l2s "," shtlst)
)
(defun l2s (delim lst / out)
  (setq out (car lst) lst (cdr lst))
  (repeat (length lst)
    (setq out (strcat out delim (car lst)) lst (cdr lst))
  )
  out
)
« Last Edit: October 21, 2021, 06:11:16 PM by mhupp »

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Page Number String From List
« Reply #3 on: October 21, 2021, 05:59:46 PM »
Did it a little bit different. Doesn't work 100% like yours with the last example. need to tweak the logic a bit.

(P#2S '(1 2 3 4 5 6 11 13 14 15 16 17 18 19 20 21 22 23))
"1-6,11,13-23"

(P#2S '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23))
"1-23"

(P#2S '(1 3 5 6))
"1,3,5-6"

Just to clarify, are you saying your code or mine doesn't work 100% with the last example?

mhupp

  • Bull Frog
  • Posts: 250
Re: Page Number String From List
« Reply #4 on: October 21, 2021, 06:08:41 PM »
my code adds the - if the two last numbers are consecutive "1,3,5-6"
Another check is it sorts the list to make sure all the numbers are in the right order.
(1 2 3 5 4 6 7 8 ) will come out 1-8 instead of 1-3, 5, 4, 6, 7, 8
« Last Edit: October 21, 2021, 06:13:16 PM by mhupp »

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Page Number String From List
« Reply #5 on: October 21, 2021, 06:12:33 PM »
Similar to that already posted -
Code - Auto/Visual Lisp: [Select]
  1. (defun lst->rng ( l / r y x )
  2.     (setq l (vl-sort l '<)
  3.           r ""
  4.     )
  5.     (while (setq x (car l))
  6.         (setq l (cdr l)
  7.               y x
  8.         )
  9.         (while (and l (= 1 (- (car l) y)))
  10.             (setq y (car l) l (cdr l))
  11.         )
  12.         (if (/= x y)
  13.             (setq r (strcat r (itoa x) "-" (itoa y) ","))
  14.             (setq r (strcat r (itoa x) ","))
  15.         )
  16.     )
  17.     (substr r 1 (1- (strlen r)))
  18. )

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Page Number String From List
« Reply #6 on: October 21, 2021, 06:16:21 PM »
Similar to that already posted -
Code - Auto/Visual Lisp: [Select]
  1. (defun lst->rng ( l / r y x )
  2.     (setq l (vl-sort l '<)
  3.           r ""
  4.     )
  5.     (while (setq x (car l))
  6.         (setq l (cdr l)
  7.               y x
  8.         )
  9.         (while (and l (= 1 (- (car l) y)))
  10.             (setq y (car l) l (cdr l))
  11.         )
  12.         (if (/= x y)
  13.             (setq r (strcat r (itoa x) "-" (itoa y) ","))
  14.             (setq r (strcat r (itoa x) ","))
  15.         )
  16.     )
  17.     (substr r 1 (1- (strlen r)))
  18. )
But yours is so much more concise at 18 lines vs my 70 or so.....lol

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Page Number String From List
« Reply #7 on: October 21, 2021, 06:22:28 PM »
Here's one for the reverse -
Code - Auto/Visual Lisp: [Select]
  1. (defun rng->lst ( r / l )
  2.     (cond
  3.         (   (= "" r) nil)
  4.         (   (wcmatch r "*`,*")
  5.             (append
  6.                 (rng->lst (substr r 1 (vl-string-position 44 r)))
  7.                 (rng->lst (substr r (+ 2 (vl-string-position 44 r))))
  8.             )
  9.         )
  10.         (   (wcmatch r "*`-*")
  11.             (setq l (list (atoi (substr r (+ 2 (vl-string-position 45 r))))))
  12.             (repeat (- (car l) (atoi (substr r 1 (vl-string-position 45 r))))
  13.                 (setq l (cons (1- (car l)) l))
  14.             )
  15.         )
  16.         (   (list (atoi r)))
  17.     )
  18. )
Code - Auto/Visual Lisp: [Select]
  1. _$ (rng->lst "1-23")
  2. (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
  3. _$ (rng->lst "1-6,11,13-23")
  4. (1 2 3 4 5 6 11 13 14 15 16 17 18 19 20 21 22 23)
  5. _$ (rng->lst "1,3,5-6")
  6. (1 3 5 6)

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Page Number String From List
« Reply #8 on: October 21, 2021, 06:33:00 PM »
Another recursive variant of the first -
Code - Auto/Visual Lisp: [Select]
  1. (defun lst->rng ( l / f )
  2.     (defun f ( x y l )
  3.         (cond
  4.             (   (null l) (if (= x y) (itoa x) (strcat (itoa x) "-" (itoa y))))
  5.             (   (< 1 (- (car l) y))
  6.                 (strcat (f x y nil) "," (f (car l) (car l) (cdr l)))
  7.             )
  8.             (   (f x (car l) (cdr l)))
  9.         )
  10.     )
  11.     (   (lambda ( l ) (if l (f (car l) (car l) (cdr l)) "")) (vl-sort l '<))
  12. )
« Last Edit: October 21, 2021, 06:37:11 PM by Lee Mac »

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Page Number String From List
« Reply #9 on: October 21, 2021, 07:03:23 PM »
Here's one for the reverse -
Code - Auto/Visual Lisp: [Select]
  1. (defun rng->lst ( r / l )
  2.     (cond
  3.         (   (= "" r) nil)
  4.         (   (wcmatch r "*`,*")
  5.             (append
  6.                 (rng->lst (substr r 1 (vl-string-position 44 r)))
  7.                 (rng->lst (substr r (+ 2 (vl-string-position 44 r))))
  8.             )
  9.         )
  10.         (   (wcmatch r "*`-*")
  11.             (setq l (list (atoi (substr r (+ 2 (vl-string-position 45 r))))))
  12.             (repeat (- (car l) (atoi (substr r 1 (vl-string-position 45 r))))
  13.                 (setq l (cons (1- (car l)) l))
  14.             )
  15.         )
  16.         (   (list (atoi r)))
  17.     )
  18. )
Code - Auto/Visual Lisp: [Select]
  1. _$ (rng->lst "1-23")
  2. (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
  3. _$ (rng->lst "1-6,11,13-23")
  4. (1 2 3 4 5 6 11 13 14 15 16 17 18 19 20 21 22 23)
  5. _$ (rng->lst "1,3,5-6")
  6. (1 3 5 6)

I am not entirely sure what the issues is here, but a string of: 1,3,5,7-10,12-15
Returns:
(1 3 5 7 8 9 10 2 3 4 5 6 7 8 9 10 11 12 13 14 15)

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Page Number String From List
« Reply #10 on: October 21, 2021, 07:17:37 PM »
For completeness, here is my code that doesn't seem to have the same error, but definitely not as concise and probably has its own issues:

Code: [Select]
  (defun String->NumberList (NumberString / str pos LeftString RightString Results Start End)
    (defun LM:str->lst ( str del / pos )
      ;; String to List  -  Lee Mac
      ;; Separates a string using a given delimiter
      ;; str - [str] String to process
      ;; del - [str] Delimiter by which to separate the string
      ;; Returns: [lst] List of strings
        (if (setq pos (vl-string-search del str))
            (cons (substr str 1 pos) (LM:str->lst (substr str (+ pos 1 (strlen del))) del))
            (list str)
        )
    )
    (setq StringList (LM:str->lst NumberString ","))
    (foreach str StringList
      (setq str (vl-string-trim " " str)
            pos (vl-string-search "-" str)
      )   
      (if (not pos)
        (progn
          (if (not Results)
            (setq Results (list (atoi str)))
            (setq Results (append Results (list (atoi str))))
          )
        )
        (progn
          (setq LeftString (substr str 1 pos)
                RightString (substr str (+ pos 2))
                Start (atoi LeftString)
                End (atoi RightString)
          )
          (if (not Results)
            (progn
              (setq Results (list Start)
                    Start (+ Start 1)
              )
            )
          )
          (while (<= Start End)
            (setq Results (append Results (list Start))
                  Start (+ Start 1)
            )
          )
        )
      )
    )
    Results
  )

mhupp

  • Bull Frog
  • Posts: 250
Re: Page Number String From List
« Reply #11 on: October 22, 2021, 09:29:56 AM »
This is why i come to the forums almost daily. Always learning, picked up several things thank you Lee.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Page Number String From List
« Reply #12 on: October 22, 2021, 11:23:28 AM »
This is why i come to the forums almost daily. Always learning, picked up several things thank you Lee.
Yeah, there I times I think Lee should be on the payroll here.....LOL

I still don't understand why I am getting the error with his second routine though.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Page Number String From List
« Reply #13 on: October 22, 2021, 01:41:14 PM »
I am confused, I got an email saying the Lee had responded, but I don't see his response here.

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Page Number String From List
« Reply #14 on: October 22, 2021, 03:22:38 PM »
I am not entirely sure what the issues is here, but a string of: 1,3,5,7-10,12-15
Returns:
(1 3 5 7 8 9 10 2 3 4 5 6 7 8 9 10 11 12 13 14 15)

It seems to work in my testing -
Code - Auto/Visual Lisp: [Select]
  1. _$ (rng->lst "1,3,5,7-10,12-15")
  2. (1 3 5 7 8 9 10 12 13 14 15)

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Page Number String From List
« Reply #15 on: October 22, 2021, 03:22:58 PM »
I am confused, I got an email saying the Lee had responded, but I don't see his response here.

Perhaps a delayed email from my earlier responses?

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Page Number String From List
« Reply #16 on: October 22, 2021, 03:23:51 PM »
This is why i come to the forums almost daily. Always learning, picked up several things thank you Lee.

You're more than welcome - I'm delighted you could benefit from the examples!  :-)