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

0 Members and 1 Guest are viewing this topic.

Grrr1337

  • Bull Frog
  • Posts: 447
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: 447
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: 867
  • 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: 447
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: 70
  • 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: 447
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: 867
  • 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: 17012
  • 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: 447
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: 70
  • 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: 867
  • 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: 8861
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: 1707
  • 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: 867
  • Ukraine
Re: Split String To Strings and Numbers
« Reply #14 on: October 03, 2017, 11:13:32 am »

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