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

0 Members and 1 Guest are viewing this topic.

ribarm

  • Water Moccasin
  • Posts: 1707
  • 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: 447
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: 447
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: 867
  • 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: 70
  • 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: 867
  • 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: 70
  • 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: 11851
  • 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: 447
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.