Author Topic: Split String To Strings and Numbers  (Read 673 times)

0 Members and 1 Guest are viewing this topic.

Grrr1337

  • Bull Frog
  • Posts: 380
Split String To Strings and Numbers
« on: October 01, 2017, 05:12:00 pm »
Hi again guys,
I was trying to figure out a function that does this:
Code - Auto/Visual Lisp: [Select]
  1. _$ (foo "Hi123SplitThis12.345String25-20") -> ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
Basically breaking a string into a list of strings and numbers.

I've searched quite a while, but the closest result was from Lee's LM:SplitString function:
Code - Auto/Visual Lisp: [Select]
  1. _$ (LM:splitstring "Hi123SplitThis12.345String25-20")
  2. ("H" "i" 123 "S" "p" "l" "i" "t" "T" "h" "i" "s" 12.345 "S" "t" "r" "i" "n" "g" 25 "-" 20)
As you can see it does character breaking, and groups those that form potential numbers.
That looks good, but if one has alphabetical fragments of unknown length the 'nth' position of the number or the string fragment would be lost:
Code - Auto/Visual Lisp: [Select]
  1. _$ (LM:splitstring "AB-420-HE5")
  2. ("A" "B" "-" 420 "-" "H" "E" 5)
  3.  
  4. _$ (LM:splitstring "ASB-430-HS56")
  5. ("A" "S" "B" "-" 430 "-" "H" "S" 56)

Atleast the labeling str patterns look more like this (where the strlen varies).
And yea I know that I could filter out the numbers in a new list and process them, but thats not the point.



So when using his subfunction along with this one (wow, he wrote the 2nd function aswell) :
Code - Auto/Visual Lisp: [Select]
  1. ; https://www.theswamp.org/index.php?topic=53354.msg580794#msg580794
  2. (defun GroupListByFoo ( prd lst / rtn tmp ) ; Lee Mac
  3.  (foreach itm lst
  4.    (if (apply prd (list itm))
  5.      (setq rtn (vl-list* (list itm) (reverse tmp) rtn) tmp nil)
  6.      (setq tmp (cons itm tmp))
  7.    )
  8.  
  9.  )
  10.  (vl-remove nil (reverse (cons (reverse tmp) rtn)))
  11. ); defun GroupListByFoo

I've managed to write a solution:
Code - Auto/Visual Lisp: [Select]
  1. _$ (mapcar
  2.  '(lambda (x) (cond ( (= 1 (length x)) (car x) ) ( (apply 'strcat x) ) ))
  3.  (GroupListByFoo
  4.    '(lambda (x) (numberp x))
  5.    (LM:splitstring "Hi123SplitThis12.345String25-20")
  6.  )
  7. )
  8. ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
But honestly I think that the above approach sucks, due the amount of proccessing/manupulating a single string..
So any ideas to write a better one from scratch?
Does this sound like a {Challenge} ? :lol:

Tharwat

  • Bull Frog
  • Posts: 500
  • Hypersensitive
Re: Split String To Strings and Numbers
« Reply #1 on: October 02, 2017, 02:10:28 am »
Hi,

Maybe this?

Code - Auto/Visual Lisp: [Select]
  1. (defun ConcatStrWithinList (lst / str rtn)
  2. ;; Tharwat - 02.Oct.2017  ;;
  3.  (setq str "")
  4.  (while lst
  5.    (if (numberp (car lst)) (setq rtn (cons (car lst) rtn) lst (cdr lst))
  6.      (progn (while (and lst (= (type (car lst)) 'str))
  7.               (setq str (strcat str (car lst))
  8.                     lst (cdr lst)
  9.                     )
  10.               )
  11.        (setq rtn (cons str rtn) str "")
  12.        )
  13.      )
  14.    )
  15.  (reverse rtn)
  16.  )
  17.  

eg:
Code - Auto/Visual Lisp: [Select]
  1. _$ (ConcatStrWithinList '("H" "i" 123 "S" "p" "l" "i" "t" "T" "h" "i" "s" 12.345 "S" "t" "r" "i" "n" "g" 25 "-" 20))
  2. ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
  3.  

Grrr1337

  • Bull Frog
  • Posts: 380
Re: Split String To Strings and Numbers
« Reply #2 on: October 02, 2017, 06:39:55 am »
Hi Tharwat,

That seems better, thanks! :)

Code - Auto/Visual Lisp: [Select]
  1. _$ (ConcatStrWithinList (LM:splitstring "Hi123SplitThis12.345String25-20"))
  2. ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)

But actually I was trying to combine all of this into a single function, i.e.:
Code - Auto/Visual Lisp: [Select]
  1. (foo "Hi123SplitThis12.345String25-20") -> ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)




So I guess thats a success... :

Code - Auto/Visual Lisp: [Select]
  1. ; Source code by Lee Mac - heavily modified his (LM:splitstring) function
  2. (defun String->ListOfStringsAndNumbers ( str / L r )
  3.  (and ; https://www.theswamp.org/index.php?topic=53496.0
  4.    (eq 'STR (type str))
  5.    (setq L (mapcar 'chr (vl-string->list str)))
  6.    (setq L
  7.      (apply 'append
  8.        (mapcar
  9.          (function
  10.            (lambda ( a b c / ai bi ci an bn cn)
  11.              (mapcar 'set '(ai bi ci) (mapcar '(lambda (x) (if x (ascii x))) (list a b c)))
  12.              (mapcar 'set '(an bn cn) (mapcar '(lambda (x) (cond ( (and x (/= "." x)) (numberp (read x))) ( (= "." x) ))) (list a b c)))
  13.              (cond
  14.                ( (= "\\" b) (list " " "\"" "\\" b "\"" " ") )
  15.                (
  16.                  ; (append ; this block is just informative and shall be erased
  17.                  ; (if a
  18.                  ; (if (or (and an (not bn)) (and (not an) bn)) (list " " "\""))
  19.                  ; (list "\"")
  20.                  ; )
  21.                  ; (list b)
  22.                  ; (if c
  23.                  ; (if (or (and cn (not bn)) (and (not cn) bn)) (list "\"" " " ))
  24.                  ; (list "\"")
  25.                  ; )
  26.                  ; ); append
  27.                  (list
  28.                    (if a
  29.                      (if (or (and an (not bn)) (and (not an) bn)) (strcat " " "\"") "")
  30.                      "\""
  31.                    )
  32.                    b
  33.                    (if c
  34.                      (if (or (and cn (not bn)) (and (not cn) bn)) (strcat "\"" " " ) "")
  35.                      "\""
  36.                    )
  37.                  ); list
  38.                )
  39.              )
  40.            )
  41.          )
  42.          (cons nil L) L (append (cdr L) '(( )))
  43.        )
  44.      )
  45.    )
  46.    (setq r
  47.      (mapcar
  48.        (function
  49.          (lambda (x / n)
  50.            (cond
  51.              ( (= "." x) )
  52.              ( (wcmatch x "`.*")
  53.                (setq n (read (strcat "0" x)))
  54.              )
  55.              ( (setq n (read x)) )
  56.            )
  57.            (cond
  58.              ( (numberp n) n)
  59.              (x)
  60.            ); cond
  61.          ); lambda
  62.        ); function
  63.        (read
  64.          (strcat "("
  65.            (apply 'strcat L)
  66.            ")"
  67.          )
  68.        )
  69.      )
  70.    )
  71.  ); and
  72.  r
  73. ); defun String->ListOfStringsAndNumbers

Results:
Code - Auto/Visual Lisp: [Select]
  1. _$ (String->ListOfStringsAndNumbers "Hi123SplitThis12.345String25-20")
  2. ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
  3.  
  4. _$ (String->ListOfStringsAndNumbers "Hi.123SplitThis12.345String25-20")
  5. ("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
  6.  
  7. _$ (String->ListOfStringsAndNumbers "Hi..123SplitThis12.345String25-20")
  8. ("Hi" "..123" "SplitThis" 12.345 "String" 25 "-" 20)




BTW heres Lee's code I mentioned previously (couldn't find it officially on his website) :
Code - Auto/Visual Lisp: [Select]
  1. ;; Split String  -  Lee Mac
  2. ;; Splits a string into a list of text and numbers
  3.  
  4. (defun LM:splitstring ( str )
  5.  (
  6.    (lambda ( l )
  7.      (read
  8.        (strcat "("
  9.          (vl-list->string
  10.            (apply 'append
  11.              (mapcar
  12.                (function
  13.                  (lambda ( a b c )
  14.                    (cond
  15.                      (   (= 92 b)
  16.                      (list 32 34 92 b 34 32)
  17.                    )
  18.                    (   (or (< 47 b 58)
  19.                      ;(and (= 45 b) (< 47 c 58) (not (< 47 a 58)))
  20.                      (and (= 46 b) (< 47 a 58) (< 47 c 58))
  21.                    )
  22.                    (list b)
  23.                    )
  24.                    (   (list 32 34 b 34 32))
  25.                  )
  26.                  )
  27.                )
  28.                (cons nil l) l (append (cdr l) '(( )))
  29.              )
  30.            )
  31.          )
  32.          ")"
  33.        )
  34.      )
  35.    )
  36.    (vl-string->list str)
  37.  )
  38. )

No idea how he is used to manipulate ASCII like that, but I agree that would be faster, than my chr conversion.  :thinking:

Thanks again for your input!

VovKa

  • Swamp Rat
  • Posts: 832
  • Ukraine
Re: Split String To Strings and Numbers
« Reply #3 on: October 02, 2017, 09:14:12 am »
quotes, double quotes, parenthesis will not pass through read function

Grrr1337

  • Bull Frog
  • Posts: 380
Re: Split String To Strings and Numbers
« Reply #4 on: October 02, 2017, 10:11:11 am »
quotes, double quotes, parenthesis will not pass through read function

Thanks Vovka, I was aware only about the dot "." issue!  :rolleyes2:

How about this quick-dirty fix? :

Code - Auto/Visual Lisp: [Select]
  1. ; _$ (read "'") -> Error: EOF after quote on input
  2. ; _$ (read "(") -> Error: malformed list on input
  3. ; _$ (read ")") -> Error: extra right paren on input
  4. ; _$ (read """") -> Error: too many arguments
  5. ; _$ (read ".") -> Error: misplaced dot on input
  6. ; _$ (read "....") -> Error: misplaced dot on input
  7. (setq ReadCarefully
  8.  (lambda (x / r)
  9.    (cond
  10.      ( (vl-catch-all-error-p (setq r (vl-catch-all-apply 'read (list x)))) x)
  11.      (r)
  12.    )
  13.  )
  14. )
  15.  
  16. _$ (mapcar 'ReadCarefully '("'" "(" ")" """" "." "..."))
  17. ("'" "(" ")" nil nil "." "...")

fools

  • Newt
  • Posts: 63
  • China
Re: Split String To Strings and Numbers
« Reply #5 on: October 02, 2017, 11:27:07 am »
Code - Auto/Visual Lisp: [Select]
  1. ;; Split String  -  Lee Mac
  2. ;; Splits a string into a list of text and numbers
  3. ;; Modified by Fools , 2011.10.2
  4. ;; (LM:splitstring-F1 "Hi123SplitThis12.345String25-20")
  5. ;; ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
  6. (defun LM:splitstring-F1 (str)
  7.  ((lambda (l)
  8.     (read
  9.       (strcat "("
  10.       (vl-list->string
  11. (mapcar (function (lambda (a b c)
  12.    (cond ((= 92 b) (list 32 34 92 b 34 32))
  13.  ((or (< 47 b 58) (and (= 46 b) (< 47 a 58) (< 47 c 58))) (list b))
  14.  ((cond ((not a) (list 34 b))
  15. ((and (< 47 a 58) (< 47 c 58)) (list 32 34 b 34 32))
  16. ((< 47 a 58) (list 32 34 b))
  17. ((< 47 c 58) (list b 34 32))
  18. ((not c) (list b 34))
  19. ((list b))
  20.   )
  21.  )
  22.    )
  23.  )
  24. )
  25. (cons nil l)
  26. l
  27. (append (cdr l) '(()))
  28. )
  29. )
  30.       )
  31.       ")"
  32.       )
  33.     )
  34.   )
  35.    (vl-string->list str)
  36.  )
  37. )
Good good study , day day up . Sorry about my Chinglish .

Grrr1337

  • Bull Frog
  • Posts: 380
Re: Split String To Strings and Numbers
« Reply #6 on: October 02, 2017, 11:40:00 am »
Thanks fools, works as expected!

More impressive is the single iteration you did, as I had to additionally process my string-list output into list of strings and numbers.
The returns in yours are slightly different, but overall suits my needs:
Code - Auto/Visual Lisp: [Select]
  1. _$ (LM:splitstring-F1 "Hi123SplitThis12.345String25-20")
  2. ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
  3.  
  4. _$ (LM:splitstring-F1 "Hi.123SplitThis12.345String25-20")
  5. ("Hi." 123 "SplitThis" 12.345 "String" 25 "-" 20)
  6.  
  7. _$ (LM:splitstring-F1 "Hi..123SplitThis12.345String25-20")
  8. ("Hi.." 123 "SplitThis" 12.345 "String" 25 "-" 20)

Code: [Select]
;; Modified by Fools , 2011.10.2Is it really from 2011 ? I was really googling hard and couldn't find something like this.

VovKa

  • Swamp Rat
  • Posts: 832
  • Ukraine
Re: Split String To Strings and Numbers
« Reply #7 on: October 02, 2017, 12:02:02 pm »
Code: [Select]
(LM:SPLITSTRING-F1 "a1")

MP

  • Seagull
  • Posts: 16992
  • brevity != aggression
Re: Split String To Strings and Numbers
« Reply #8 on: October 02, 2017, 12:42:46 pm »
For what it's worth (idea fodder) I wrote these ages ago. That said, the intent was to break out integers and delims from text (specifially filenames at the time), not reals. Don't have time at present to play with the latter as fun as that would be.

Code: [Select]
(defun _Rupture ( text )
    ;;  © 2017 Michael Puckett
    ;;  (_Rupture "X911.02-3C-0001.dwg")
    ;;  >> ("X" "911" "." "02" "-" "3" "C" "-" "0001" "." "dwg")
    (   (lambda ( f1 f2 l / x r )
            (foreach i (setq x (list (car l)) l (cdr l))
                (if (f1 i x)
                    (setq x (cons i x))
                    (setq r (cons x r) x (list i))
                )
            )
            (mapcar 'vl-list->string (cons x r))
        )
        (lambda (i x) (eq (f2 i) (f2 (car x))))
        (lambda (i) (cond ((or (< 64 i 91) (< 96 i 123)) 2) ((< 47 i 58) 1) ((< 32 i 128) 3) ((< -1 i 33) 0) (i 4)))
        (reverse (vl-string->list text))
    )
)

Code: [Select]
(defun _Fission ( text )
    ;;  © 2017 Michael Puckett
    ;;  (_Fission "X911.02-3C-0001.dwg")
    ;;  >> ("X" 911 "." 2 "-" 3 "C" "-" 1 "." "dwg")
    (   (lambda ( white )
            (mapcar
                (function (lambda (s) (if (wcmatch s "#*") (read s) (vl-string-trim white s))))
                (_Rupture text)
            )
        )
        (strcat " " (chr 160) "\n\r\t")
    )
)

Cheers.
\|// Set goal. Experiment tirelessly until
|oo| practice has become expertise.  Loop.
|- | LinkedIn | Dropbox | About

Grrr1337

  • Bull Frog
  • Posts: 380
Re: Split String To Strings and Numbers
« Reply #9 on: October 02, 2017, 03:44:06 pm »

Code: [Select]
(LM:SPLITSTRING-F1 "a1")

You are good at spotting eventual problems, guess I'll stick to mine version untill figuring out the fix for fool's modification.



For what it's worth (idea fodder) I wrote these ages ago.

Thanks for your input, Michael!

That said, the intent was to break out integers and delims from text (specifially filenames at the time), not reals.

I'm not sure whats the proper kind of labeling (only integers? no negatives?) when using alphanumerical strings - guess that depends on the company's standards.
I don't have current task to manipulate such strings (but theres always a first time) and thought that having such subfunction would be very useful.

Don't have time at present to play with the latter as fun as that would be.

Thats sad, also it seems that Lee is also busy (haven't been active in a while in the recent topics).
But I thought leaving the thread for the future, when anyone got free time.. (overall I'm leaving ideas in different threads here and there..).

fools

  • Newt
  • Posts: 63
  • China
Re: Split String To Strings and Numbers
« Reply #10 on: October 02, 2017, 08:54:21 pm »
Code: [Select]
(LM:SPLITSTRING-F1 "a1")

Code: [Select]
;; Modified by Fools , 2011.10.2Is it really from 2011 ? I was really googling hard and couldn't find something like this.

I rewritten the wrong code, and corrected the modification time.  :grinwink:

Code - Auto/Visual Lisp: [Select]
  1. ;; Split String  -  Lee Mac
  2. ;; Splits a string into a list of text and numbers
  3. ;; Modified by Fools , 2017.10.3
  4. ;; (LM:splitstring-F2 "Hi.123SplitThis12.345String25-20")
  5. ;; ("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
  6. (defun LM:splitstring-F2 (str)
  7.  ((lambda (l)
  8.     (read
  9.       (strcat "("
  10.       (vl-list->string
  11. (mapcar (function (lambda (a b c)
  12.    (cond ((= 92 b) (list 32 34 92 b 34 32)) ;_\
  13.  ((< 47 b 58)  (list b)) ;_num
  14.  ((and (= 46 b) (< 47 c 58)) (if (< 47 a 58) (list b) (list 34 48 b))) ;_.
  15.  ((cond ((not a) ;_begin
  16.  (if (< 47 c 58)
  17.    (list 34 b 34)
  18.    (list 34 b)
  19.  )
  20. )
  21. ((not c) ;_end
  22.  (if (< 47 a 58)
  23.    (list 34 b 34)
  24.    (list b 34)
  25.  )
  26. )
  27. ((and (< 47 a 58) (< 47 c 58)) (list 34 b 34))
  28. ((< 47 a 58) (list 34 b))
  29. ((< 47 c 58) (list b 34))
  30. ((list b))
  31.   )
  32.  )
  33.    )
  34.  )
  35. )
  36. (cons nil l)
  37. l
  38. (append (cdr l) '(()))
  39. )
  40. )
  41.       )
  42.       ")"
  43.       )
  44.     )
  45.   )
  46.    (vl-string->list str)
  47.  )
  48. )


_$ (LM:splitstring-F2 "Hi.123SplitThis12.345String25-20")
("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
_$ (LM:splitstring-F2 "Hi123SplitThis12.345String25-20")
("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
_$ (LM:splitstring-F2 "Hi.123SplitThis12.345String25-20")
("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
_$ (LM:splitstring-F2 "Hi..123SplitThis12.345String25-20")
("Hi." 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
_$ (LM:splitstring-F2 "a1")
("a" 1)
_$ (LM:splitstring-F2 "1a")
(1 "a")
Good good study , day day up . Sorry about my Chinglish .

VovKa

  • Swamp Rat
  • Posts: 832
  • Ukraine
Re: Split String To Strings and Numbers
« Reply #11 on: October 03, 2017, 05:36:48 am »
Code: [Select]
(LM:splitstring-F2 "a")

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 8806
Re: Split String To Strings and Numbers
« Reply #12 on: October 03, 2017, 09:06:03 am »
lol!

I've written a few parsers (in C and C++) and they are very fun. I had to put my last compiler project aside because it was generating a nasty segfault somewhere in my real's parsing I just couldn't track down.

I've been looking at the code of that function "LM:splitstring.." and I somewhat understand it (at a high level) and it is approaching the problem in the same way as I would (in lisp) -i.e. operating on char codes but I'd be tempted to use a recursive type function in this instance (not a loop or a map function). Of course recursion will not get you real detection (or at least an efficient one) but, you may be able to handle a few of the special cases easier. A recursive method--in this application--has inherent problems vs a loop/map type function but you may need to weigh the good's and bad's of each different type against the specific case at hand.

Sorry, that post wasn't worth much but I was just trying to add to the conversation.
“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

ribarm

  • Water Moccasin
  • Posts: 1682
  • Marko Ribar, architect
Re: Split String To Strings and Numbers
« Reply #13 on: October 03, 2017, 09:58:00 am »
Code: [Select]
(LM:splitstring-F2 "a")

Code - Auto/Visual Lisp: [Select]
  1. ;; Split String  -  Lee Mac
  2. ;; Splits a string into a list of text and numbers
  3. ;; Modified by Fools , 2017.10.3
  4. ;; (LM:splitstring-F2 "Hi.123SplitThis12.345String25-20")
  5. ;; ("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
  6. (defun LM:splitstring-F2 ( str )
  7.  ( (lambda ( l )
  8.      (read
  9.        (strcat
  10.          "("
  11.          (vl-list->string
  12.            (apply
  13.              (function append)
  14.                (mapcar
  15.                  (function
  16.                    (lambda ( a b c )
  17.                      (cond
  18.                        ( (and (not a) (not c) (< 47 b 58))
  19.                          (list b)
  20.                        ) ;_single num
  21.                        ( (and (not a) (not c))
  22.                          (list 34 b 34)
  23.                        ) ;_single string
  24.                        ( (= 92 b)
  25.                          (list 32 34 92 b 34 32)
  26.                        ) ;_\
  27.                        ( (< 47 b 58)
  28.                          (list b)
  29.                        ) ;_num
  30.                        ( (and (= 46 b) (< 47 c 58))
  31.                          (if (< 47 a 58)
  32.                            (list b)
  33.                            (list 34 48 b)
  34.                          )
  35.                        ) ;_.
  36.                        ( (cond
  37.                            ( (not a) ;_begin
  38.                              (if (< 47 c 58)
  39.                                (list 34 b 34)
  40.                                (list 34 b)
  41.                              )
  42.                            )
  43.                            ( (not c) ;_end
  44.                              (if (< 47 a 58)
  45.                                (list 34 b 34)
  46.                                (list b 34)
  47.                              )
  48.                            )
  49.                            ( (and (< 47 a 58) (< 47 c 58))
  50.                              (list 34 b 34)
  51.                            )
  52.                            ( (< 47 a 58)
  53.                              (list 34 b)
  54.                            )
  55.                            ( (< 47 c 58)
  56.                              (list b 34)
  57.                            )
  58.                            ( (list b) )
  59.                          )
  60.                        )
  61.                      )
  62.                    )
  63.                  )
  64.                  (cons nil l)
  65.                  l
  66.                  (append (cdr l) '(()))
  67.                )
  68.            )
  69.          )
  70.          ")"
  71.        )
  72.      )
  73.    )
  74.    (vl-string->list str)
  75.  )
  76. )
  77.  
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

VovKa

  • Swamp Rat
  • Posts: 832
  • Ukraine
Re: Split String To Strings and Numbers
« Reply #14 on: October 03, 2017, 11:13:32 am »

 :-)
Code: [Select]
(LM:splitstring-F2 "\\")

ribarm

  • Water Moccasin
  • Posts: 1682
  • Marko Ribar, architect
Re: Split String To Strings and Numbers
« Reply #15 on: October 03, 2017, 11:50:36 am »
I am not  :devilsidesmile:
I'll just exclude all not valid strings and among them is your one...

Code - Auto/Visual Lisp: [Select]
  1. ;; Split String  -  Lee Mac
  2. ;; Splits a string into a list of text and numbers
  3. ;; Modified by Fools , 2017.10.3
  4. ;; Modified by MR , 2017.10.3
  5. ;; (LM:splitstring-F3 "Hi.123SplitThis12.345String25-20")
  6. ;; ("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
  7. (defun LM:splitstring-F3 ( str )
  8.  (if (snvalid str)
  9.    (read
  10.      ( (lambda ( l )
  11.          (strcat
  12.            "("
  13.            (vl-list->string
  14.              (apply
  15.                (function append)
  16.                  (mapcar
  17.                    (function
  18.                      (lambda ( a b c )
  19.                        (cond
  20.                          ( (and (not a) (not c) (< 47 b 58))
  21.                            (list b)
  22.                          ) ;_single num
  23.                          ( (and (not a) (not c) (= 92 b))
  24.                            (list 34 92 b 34)
  25.                          ) ;_single \
  26.                          ( (and (not a) (not c))
  27.                            (list 34 b 34)
  28.                          ) ;_single alpha
  29.                          ( (= 92 b)
  30.                            (list 34 92 b 34)
  31.                          ) ;_\
  32.                          ( (< 47 b 58)
  33.                            (list b)
  34.                          ) ;_num
  35.                          ( (and (= 46 b) (< 47 c 58))
  36.                            (if (< 47 a 58)
  37.                              (list b)
  38.                              (list 34 48 b)
  39.                            )
  40.                          ) ;_.
  41.                          ( (cond
  42.                              ( (not a) ;_begin
  43.                                (if (< 47 c 58)
  44.                                  (list 34 b 34)
  45.                                  (list 34 b)
  46.                                )
  47.                              )
  48.                              ( (not c) ;_end
  49.                                (if (< 47 a 58)
  50.                                  (list 34 b 34)
  51.                                  (list b 34)
  52.                                )
  53.                              )
  54.                              ( (and (< 47 a 58) (< 47 c 58))
  55.                                (list 34 b 34)
  56.                              )
  57.                              ( (< 47 a 58)
  58.                                (list 34 b)
  59.                              )
  60.                              ( (< 47 c 58)
  61.                                (list b 34)
  62.                              )
  63.                              ( (list b) )
  64.                            )
  65.                          )
  66.                        )
  67.                      )
  68.                    )
  69.                    (cons nil l)
  70.                    l
  71.                    (append (cdr l) '(()))
  72.                  )
  73.              )
  74.            )
  75.            ")"
  76.          )
  77.        )
  78.        (vl-string->list str)
  79.      )
  80.    )
  81.    (progn
  82.      (princ "\nSpecified string is not valid...")
  83.      (princ)
  84.    )
  85.  )
  86. )
  87.  
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Grrr1337

  • Bull Frog
  • Posts: 380
Re: Split String To Strings and Numbers
« Reply #16 on: October 03, 2017, 03:47:19 pm »
Nice work, Marko!

Code - Auto/Visual Lisp: [Select]
  1. _$ (LM:splitstring-F3 "Hi123SplitThis12.345String25-20")
  2. ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
  3.  
  4. _$ (LM:splitstring-F3 "Hi.123SplitThis12.345String25-20")
  5. ("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
  6.  
  7. _$ (LM:splitstring-F3 "Hi..123SplitThis12.345String25-20")
  8. ("Hi." 0.123 "SplitThis" 12.345 "String" 25 "-" 20)

Just a minor changes I would do:

Change
Code - Auto/Visual Lisp: [Select]
  1. (if (snvalid str)
To:
Code - Auto/Visual Lisp: [Select]
  1. (if (and (eq 'STR (type str)) (snvalid str))
 
Change
Code - Auto/Visual Lisp: [Select]
  1.  (princ "\nSpecified string is not valid...")
  2.  (princ)
  3. )
To:
Code - Auto/Visual Lisp: [Select]
  1. (prompt "\nSpecified string is not valid...")


Looks like alot of conditionals are going on.  :woow:

Grrr1337

  • Bull Frog
  • Posts: 380
Re: Split String To Strings and Numbers
« Reply #17 on: October 03, 2017, 04:33:07 pm »
I've been looking at the code of that function "LM:splitstring.." and I somewhat understand it (at a high level) and it is approaching the problem in the same way as I would (in lisp) -
i.e. operating on char codes
I'd say more impressive is the idea of supplying 3 arguments, say they represent (<Previous> <Current> <Next>) characters(string atoms)
and then theres the not-so-easy conditional part to investigate when to group/split (by operating with chr codes like you mentioned).

but I'd be tempted to use a recursive type function in this instance (not a loop or a map function).
I guess that the big conditional part might be the reason for this. (as I understood conditionals and recursions go together like socks'n'shoes).

Of course recursion will not get you real detection (or at least an efficient one) but, you may be able to handle a few of the special cases easier.
A recursive method--in this application--has inherent problems vs a loop/map type function but you may need to weigh the good's and bad's of each different type against the specific case at hand.
As long one does not deal with nested lists/arrays I don't see any difference between recursion and iteration - since one does not need to dig more than the 1st level.
In this case we're just proccessing a single string so.. its not that hard to translate that code to recursive type (see below code).
Or maybe I misunderstood what you ment?

Sorry, that post wasn't worth much but I was just trying to add to the conversation.
Appreciated, I like this forum because most users involve into discussions to solve/understand problems and not just copy/pasting codes.



Code - Auto/Visual Lisp: [Select]
  1. _$ (RecursiveSplitString "Hi123SplitThis12.345String25-20")
  2. ("Hi" 123 "SplitThis" 12.345 "String" 25 "-" 20)
  3.  
  4. _$ (RecursiveSplitString "Hi.123SplitThis12.345String25-20")
  5. ("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
  6.  
  7. _$ (RecursiveSplitString "Hi..123SplitThis12.345String25-20")
  8. ("Hi." 0.123 "SplitThis" 12.345 "String" 25 "-" 20)


Code - Auto/Visual Lisp: [Select]
  1. (defun RecursiveSplitString ( str / rec L )
  2.  ;; https://www.theswamp.org/index.php?topic=53496.0
  3.  ;; Based on Lee's (LM:splitstring) function and the following modifications:
  4.  ;; Modified by Fools , 2017.10.3
  5.  ;; Modified by MR , 2017.10.3
  6.  (defun rec ( L / a b c )
  7.    (mapcar 'set '(a b c) (list (car L) (cadr L) (caddr L)))
  8.    (cond
  9.      ( (vl-every 'null (list a b c)) nil)
  10.      (
  11.        (cons
  12.          (cond
  13.            ( (and (not a) (not c) (< 47 b 58))
  14.              (list b)
  15.            ) ;_single num
  16.            ( (and (not a) (not c) (= 92 b))
  17.              (list 34 92 b 34)
  18.            ) ;_single \
  19.            ( (and (not a) (not c))
  20.              (list 34 b 34)
  21.            ) ;_single alpha
  22.            ( (= 92 b)
  23.              (list 34 92 b 34)
  24.            ) ;_\
  25.            ( (< 47 b 58)
  26.              (list b)
  27.            ) ;_num
  28.            ( (and (= 46 b) (< 47 c 58))
  29.              (if (< 47 a 58)
  30.                (list b)
  31.                (list 34 48 b)
  32.              )
  33.            ) ;_.
  34.            (
  35.              (cond
  36.                ( (not a) ;_begin
  37.                  (if (< 47 c 58)
  38.                    (list 34 b 34)
  39.                    (list 34 b)
  40.                  )
  41.                )
  42.                ( (not c) ;_end
  43.                  (if (< 47 a 58)
  44.                    (list 34 b 34)
  45.                    (list b 34)
  46.                  )
  47.                )
  48.                ( (and (< 47 a 58) (< 47 c 58))
  49.                  (list 34 b 34)
  50.                )
  51.                ( (< 47 a 58)
  52.                  (list 34 b)
  53.                )
  54.                ( (< 47 c 58)
  55.                  (list b 34)
  56.                )
  57.                ( (list b) )
  58.              )
  59.            )
  60.          ); cond
  61.          (rec (cdr L))
  62.        ); append
  63.      )
  64.    )
  65.  ); defun rec
  66.  
  67.  (cond
  68.    ( (not (eq 'STR (type str))) (prompt "\nNo string supplied.") )
  69.    ( (not (snvalid str)) (prompt "\nInvalid string supplied.") )
  70.    ( (setq L (rec (cons nil (vl-string->list str))))
  71.      (vl-remove '"" (read (strcat "(" (vl-list->string (vl-remove 'nil (apply 'append L))) ")")))
  72.    )
  73.  ); cond
  74.  
  75. ); defun RecursiveSplitString

VovKa

  • Swamp Rat
  • Posts: 832
  • Ukraine
Re: Split String To Strings and Numbers
« Reply #18 on: October 03, 2017, 05:06:26 pm »
I am not  :devilsidesmile:
I'll just exclude all not valid strings and among them is your one...
one more :)
Code: [Select]
(LM:splitstring-F3 ".1")

p.s.
snvalid is too restrictive to be used with simple strings

fools

  • Newt
  • Posts: 63
  • China
Re: Split String To Strings and Numbers
« Reply #19 on: October 03, 2017, 11:58:15 pm »
Code: [Select]
(LM:splitstring-F2 "a")
Code: [Select]
(LM:splitstring-F2 "\\")
Code: [Select]
(LM:splitstring-F3 ".1")

The function is used to "split" a string into a list of text and numbers. If all are characters or only have numbers, maybe check it out before call this function will be better.

Code - Auto/Visual Lisp: [Select]
  1. ;; Split String  -  Lee Mac
  2. ;; Splits a string into a list of text and numbers
  3. ;; Modified by Fools , 2017.10.3
  4. ;; Modified by MR , 2017.10.3
  5. ;; Modified by Fools , 2017.10.4
  6. ;; (LM:splitstring-F4 "Hi.123SplitThis12.345String25-20")
  7. ;; ("Hi" 0.123 "SplitThis" 12.345 "String" 25 "-" 20)
  8. (defun LM:splitstring-F4 (str)
  9.  (cond ((distof str) (list (distof str))) ;_check all are numbers(put it out of the function maybe better)
  10. ((wcmatch str "?") (list str)) ;_one char(put it out of the function maybe better)
  11. ((read
  12.   ((lambda (l)
  13.      (strcat "("
  14.      (vl-list->string
  15.       (mapcar (function (lambda (a b c)
  16.   (cond ((= 92 b) (list 32 34 92 b 34 32)) ;_ \
  17. ((< 47 b 58) (list b)) ;_ num
  18. ((and (= 46 b) (< 47 c 58))  ;_ dot
  19.  (cond ((not a) (list 48 b)) ;_ dot is first char
  20. ((< 47 a 58) (list b))
  21. ((list 34 48 b))
  22.  )
  23. )
  24. ((cond ((not a) ;_ begin
  25. (if (< 47 c 58)
  26.   (list 34 b 34)
  27.   (list 34 b)
  28. )
  29. )
  30. ((not c) ;_ end
  31. (if (< 47 a 58)
  32.   (list 34 b 34)
  33.   (list b 34)
  34. )
  35. )
  36. ((and (< 47 a 58) (< 47 c 58)) (list 34 b 34))
  37. ((< 47 a 58) (list 34 b))
  38. ((< 47 c 58) (list b 34))
  39. ((list b))
  40.  )
  41. )
  42.   )
  43. )
  44.       )
  45.       (cons nil l)
  46.       l
  47.       (append (cdr l) '(()))
  48.       )
  49. )
  50.      )
  51.      ")"
  52.      )
  53.    )
  54.     (vl-string->list str)
  55.   )
  56. )
  57. )
  58.  )
  59. )
« Last Edit: October 04, 2017, 12:28:03 am by fools »
Good good study , day day up . Sorry about my Chinglish .

VovKa

  • Swamp Rat
  • Posts: 832
  • Ukraine
Re: Split String To Strings and Numbers
« Reply #20 on: October 04, 2017, 05:23:02 am »
The function is used to "split" a string into a list of text and numbers. If all are characters or only have numbers, maybe check it out before call this function will be better.
but distof will return float
(LM:splitstring-F4 "1")

there is one more thing i want to pay attention to (i'm not saying it's an error):
(setq a 1.) is OK
(setq a .1) is error
but your function returns the opposite (LM:splitstring-F4 "a1.b.1")

fools

  • Newt
  • Posts: 63
  • China
Re: Split String To Strings and Numbers
« Reply #21 on: October 04, 2017, 07:50:34 am »
I don't think "LM:splitstring-F5" is better than the past, because more operations on the decimal point will reduce efficiency.
It's difficult to obtain strings such as "1." or ".1", unless it is intended.
Normally, it's almost impossible to encounter a decimal point not between two numbers.

Code - Auto/Visual Lisp: [Select]
  1. ;; Split String  -  Lee Mac
  2. ;; Splits a string into a list of text and numbers
  3. ;; Modified by Fools , 2017.10.3
  4. ;; Modified by MR , 2017.10.3
  5. ;; Modified by Fools , 2017.10.4
  6. ;;  (LM:splitstring-F5 ".1 .2ab2.cd.211dca234.")
  7. ;; (0.1 " " 0.2 "ab" 2.0 "cd" 0.211 "dca" 234.0)
  8. (defun LM:splitstring-F5 (str)
  9.  (cond ((distof str) ;_numbers (put it out of the function maybe better)
  10. (if (vl-string-search "." str)
  11.   (list (distof str))
  12.   (list (atoi str))
  13. )
  14. )
  15. ((= (strlen str) 1) (list str)) ;_one char(put it out of the function maybe better)
  16. ((read ((lambda (l)
  17.  (strcat "("
  18.  (vl-list->string
  19.    (apply 'append
  20.   (mapcar (function (lambda (a b c)
  21.       (cond ((= 92 b) (list 32 34 92 b 34 32)) ;_ \
  22.     ((< 47 b 58) (list b)) ;_ num
  23.     ((not a) ;_ begin
  24.      (if (< 47 c 58)
  25. (if (= 46 b) ;_dot
  26.  (list 48 b)
  27.  (list 34 b 34)
  28. )
  29. (list 34 b)
  30.      )
  31.     )
  32.     ((not c) ;_ end
  33.      (if (< 47 a 58)
  34. (if (= 46 b)
  35.  (list b 48)
  36.  (list 34 b 34)
  37. )
  38. (list b 34)
  39.      )
  40.     )
  41.     ((and (< 47 a 58) (< 47 c 58))
  42.      (if (= 46 b)
  43. (list b)
  44. (list 34 b 34)
  45.      )
  46.     )
  47.     ((< 47 c 58)
  48.      (if (= 46 b)
  49. (list 34 48 b)
  50. (list b 34)
  51.      )
  52.     )
  53.     ((< 47 a 58)
  54.      (if (= 46 b)
  55. (list b 48 34)
  56. (list 34 b)
  57.      )
  58.     )
  59.     ((list b))
  60.       )
  61.     )
  62.   )
  63.   (cons nil l)
  64.   l
  65.   (append (cdr l) '(()))
  66.   )
  67.    )
  68.  )
  69.  ")"
  70.  )
  71. )
  72. (vl-string->list str)
  73.       )
  74. )
  75. )
  76.  )
  77. )

_$  (LM:splitstring-F5 ".1 .2ab2.cd.211dca234.")
(0.1 " " 0.2 "ab" 2.0 "cd" 0.211 "dca" 234.0)
_$  (LM:splitstring-F5 "1")
(1)
_$  (LM:splitstring-F5 "1.")
(1.0)
_$  (LM:splitstring-F5 ".1")
(0.1)
_$  (LM:splitstring-F5 ".1 2.")
(0.1 " " 2.0)
_$  (LM:splitstring-F5 ".12.")
(0)   error...
Good good study , day day up . Sorry about my Chinglish .

Lee Mac

  • Seagull
  • Posts: 11793
  • AutoCAD 2015 Windows 7 London, England
Re: Split String To Strings and Numbers
« Reply #22 on: October 07, 2017, 05:55:43 am »
A bit late to the party...

To offer another approach, below is the function that I use as part of my Incremental Array program:
Code - Auto/Visual Lisp: [Select]
  1. (defun incarray:splitstring ( str / lst )
  2.    (setq lst (vl-string->list str))
  3.    (read (vl-list->string (vl-list* 40 34 (incarray:split lst (< 47 (car lst) 58)))))
  4. )
  5. (defun incarray:split ( lst flg )
  6.    (cond
  7.        (   (null lst) '(34 41))
  8.        (   (member (car lst) '(34 92))
  9.            (if flg
  10.                (vl-list* 34 32 34 92 (car lst) (incarray:split (cdr lst) nil))
  11.                (vl-list* 92 (car lst) (incarray:split (cdr lst) flg))
  12.            )
  13.        )
  14.        (   (or (< 47 (car lst) 58) (and (= 46 (car lst)) flg (< 47 (cadr lst) 58)))
  15.            (if flg
  16.                (vl-list* (car lst) (incarray:split (cdr lst) flg))
  17.                (vl-list* 34 32 34 (car lst) (incarray:split (cdr lst) t))
  18.            )
  19.        )
  20.        (   flg (vl-list* 34 32 34 (car lst) (incarray:split (cdr lst) nil)))
  21.        (   (vl-list* (car lst) (incarray:split (cdr lst) nil)))
  22.    )
  23. )

This could also be written iteratively:
Code - Auto/Visual Lisp: [Select]
  1. (defun LM:splitstring ( str )
  2.    (
  3.        (lambda ( l / f )
  4.            (read
  5.                (strcat "(\""
  6.                    (vl-list->string
  7.                        (apply 'append
  8.                            (mapcar
  9.                                (function
  10.                                    (lambda ( a b c )
  11.                                        (cond
  12.                                            (   (member b '(34 92))
  13.                                                (if f
  14.                                                    (progn (setq f nil) (list 34 32 34 92 b))
  15.                                                    (list 92 b)
  16.                                                )
  17.                                            )
  18.                                            (   (or (< 47 b 58) (and (= 46 b) f (< 47 c 58)))
  19.                                                (if (or f (not a))
  20.                                                    (progn (setq f t) (list b))
  21.                                                    (progn (setq f t) (list 34 32 34 b))
  22.                                                )
  23.                                            )
  24.                                            (   f
  25.                                                (setq f nil)
  26.                                                (list 34 32 34 b)
  27.                                            )
  28.                                            (   (list b))
  29.                                        )
  30.                                    )
  31.                                )
  32.                                (cons nil l) l (append (cdr l) '(( )))
  33.                            )
  34.                        )
  35.                    )
  36.                    "\")"
  37.                )
  38.            )
  39.        )
  40.        (vl-string->list str)
  41.    )
  42. )

Code - Auto/Visual Lisp: [Select]
  1. _$ (LM:splitstring "Hi123SplitThis12.345String25-20")
  2. ("Hi" "123" "SplitThis" "12.345" "String" "25" "-" "20")
  3. _$ (LM:splitstring "1\"2")
  4. ("1" "\"" "2")
  5. _$ (LM:splitstring "1\\2")
  6. ("1" "\\" "2")

In my opinion, converting the numerical items from strings to numbers would limit the uses of this function in some cases, as information is lost during the conversion process. My original 'Split String' function was used as part of a sorting function in which the loss of such information was unimportant, but given an application such as my Incremental Array program, converting the string data at the parsing stage would lose leading & trailing zeros.
« Last Edit: October 07, 2017, 06:00:08 am by Lee Mac »

Grrr1337

  • Bull Frog
  • Posts: 380
Re: Split String To Strings and Numbers
« Reply #23 on: October 07, 2017, 12:59:41 pm »
A bit late to the party...

Welcome - good to see you again! :)
So I guess that your iterative version behaves like this one (String->ListOfStringsAndNumbers), well without this extra proccessing in the end:
 
Code - Auto/Visual Lisp: [Select]
  1. (setq r
  2.    (mapcar
  3.      (function
  4.        (lambda (x / n)
  5.          (cond
  6.            ( (= "." x) )
  7.            ( (wcmatch x "`.*")
  8.              (setq n (read (strcat "0" x)))
  9.            )
  10.            ( (setq n (read x)) )
  11.          )
  12.          (cond
  13.            ( (numberp n) n)
  14.            (x)
  15.          ); cond
  16.        ); lambda
  17.      ); function
  18.      (read
  19.        (strcat "("
  20.          (apply 'strcat L)
  21.          ")"
  22.        )
  23.      )
  24.    )
  25.  )
The hard part was to include this within the main iteration as fools and Marko were attempting.