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

0 Members and 1 Guest are viewing this topic.

ribarm

  • Gator
  • Posts: 3225
  • 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

  • Swamp Rat
  • Posts: 812
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:
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Grrr1337

  • Swamp Rat
  • Posts: 812
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
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

VovKa

  • Water Moccasin
  • Posts: 1626
  • 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: 72
  • 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.                         (apply 'append
  16.                                (mapcar (function (lambda (a b c)
  17.                                                    (cond ((= 92 b) (list 32 34 92 b 34 32)) ;_ \
  18.                                                          ((< 47 b 58) (list b)) ;_ num
  19.                                                          ((and (= 46 b) (< 47 c 58))  ;_ dot
  20.                                                           (cond ((not a) (list 48 b)) ;_ dot is first char
  21.                                                                 ((< 47 a 58) (list b))
  22.                                                                 ((list 34 48 b))
  23.                                                           )
  24.                                                          )
  25.                                                          ((cond ((not a) ;_ begin
  26.                                                                  (if (< 47 c 58)
  27.                                                                    (list 34 b 34)
  28.                                                                    (list 34 b)
  29.                                                                  )
  30.                                                                 )
  31.                                                                 ((not c) ;_ end
  32.                                                                  (if (< 47 a 58)
  33.                                                                    (list 34 b 34)
  34.                                                                    (list b 34)
  35.                                                                  )
  36.                                                                 )
  37.                                                                 ((and (< 47 a 58) (< 47 c 58)) (list 34 b 34))
  38.                                                                 ((< 47 a 58) (list 34 b))
  39.                                                                 ((< 47 c 58) (list b 34))
  40.                                                                 ((list b))
  41.                                                           )
  42.                                                          )
  43.                                                    )
  44.                                                  )
  45.                                        )
  46.                                        (cons nil l)
  47.                                        l
  48.                                        (append (cdr l) '(()))
  49.                                )
  50.                         )
  51.                       )
  52.                       ")"
  53.               )
  54.             )
  55.              (vl-string->list str)
  56.            )
  57.          )
  58.         )
  59.   )
  60. )
« Last Edit: October 04, 2017, 12:28:03 AM by fools »
Good good study , day day up . Sorry about my Chinglish .

VovKa

  • Water Moccasin
  • Posts: 1626
  • 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: 72
  • 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: 12906
  • 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

  • Swamp Rat
  • Posts: 812
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.
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Split String To Strings and Numbers
« Reply #24 on: December 23, 2017, 05:19:40 PM »
I know this thread is getting old, but I've just attempted this - and seems to work well:
Code - Auto/Visual Lisp: [Select]
  1. ; _$ (SplitStrToStrAndNumbers "Simple split examp73")
  2. ; >> ("Simple" "split" "examp" 73)
  3.  
  4. ; _$ (SplitStrToStrAndNumbers "Extract 123,4 These Lucky56 Num7 ber89,0s.532 ,42 .")
  5. ; >> ("Extract" 123.4 "These" "Lucky" 56 "Num" 7 "ber" 89.0 "s." 532 " ,42" " .")
  6.  
  7. ; _$ (SplitStrToStrAndNumbers "Split123,4This String56 In7o L1s7,0 of 57.r1ngs and n.895s .1 ,1")
  8. ; >> ("Split" 123.4 "This" "String" 56 "In" 7 "o" "L" 1 "s" 7.0 "of" 57.0 "r" 1 "ngs" "and" "n." 895 "s" " .1" " ,1") ; <- if theres no integer/zero infront of the "." - it won't be treated as decimal
  9.  
  10. ; _$ (SplitStrToStrAndNumbers "Split123,4This String56 In7o L1s7,0 of 57.r1ngs and n0.895 0.1 0,1")
  11. ; >> ("Split" 123.4 "This" "String" 56 "In" 7 "o" "L" 1 "s" 7.0 "of" 57.0 "r" 1 "ngs" "and" "n" 0.895 0.1 0.1)
  12.  
  13. ; _$ (SplitStrToStrAndNumbers "Theres 1. week and 1 day till 31/12/2017, so that makes 192,3 hours and 0.5 minutes.")
  14. ; >> ("Theres" 1.0 "week" "and" 1 "day" "till" 31 "/" 12 "/" 2017.0 "so" "that" "makes" 192.3 "hours" "and" 0.5 "minutes.")
  15. (defun SplitStrToStrAndNumbers ( str / rgx mc2 tmp tmp2 L )
  16.   ; https://www.theswamp.org/index.php?topic=53496.15
  17.   ; Split a string into a list of strings and numbers, using regular expressions
  18.   ; Credits: M.Puckett, Lee Mac, Roy
  19.   ;| Attempts:  
  20.   \d*[\.,]\d*|\d*|$  
  21.   [^\d\s]*[^\d\s]|\d*[\.,]\d*|\d*|$  
  22.   \d*[\.,]\d*|[^\d\s]*[^\d\s]|\d*|$  
  23.   \d*[\.,]\d*|(?:[^A-Z_a-z])[.,]\d*|[^\d\s]*[^\d\s]|\d*|$
  24.   |;
  25.   (vl-catch-all-apply
  26.     (function
  27.       (lambda nil
  28.         (setq rgx (vlax-get-or-create-object "vbscript.regexp"))
  29.         (vlax-put-property rgx 'global     actrue)
  30.         (vlax-put-property rgx 'ignorecase actrue)
  31.         (vlax-put-property rgx 'multiline  actrue)
  32.         (vlax-put-property rgx 'pattern    "\\d*[\\.,]\\d*|(?:[^A-Z_a-z])[.,]\\d*|[^\\d\\s]*[^\\d\\s]|\\d*|$") ; I used " " as delimeter (not sure if I wanted tho)
  33.         (vlax-for o (setq mc2 (vlax-invoke-method rgx 'Execute str))
  34.           (cond
  35.             ( (= "" (setq tmp (vlax-get-property o 'Value))) )
  36.             ( (progn (setq tmp2 (vl-catch-all-apply 'read (list (vl-string-subst "." "," tmp)))) nil) )
  37.             ( (setq L (cons (cond ( (or (vl-catch-all-error-p tmp2) (eq 'SYM (type tmp2))) tmp) (tmp2)) L)) )
  38.           ); cond
  39.         ); vlax-for
  40.       ); lambda
  41.     ); function
  42.   ); vl-catch-all-apply
  43.   (vl-catch-all-apply 'vlax-release-object (list rgx)) (reverse L)
  44. ); defun SplitStrToStrAndNumbers

Accreditation to the guys that introduced me into regex (getting started) - Although I'm still learning, so there might be bugs.
« Last Edit: December 23, 2017, 05:24:29 PM by Grrr1337 »
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Dlanor

  • Bull Frog
  • Posts: 263
Re: Split String To Strings and Numbers
« Reply #25 on: March 09, 2018, 06:02:12 PM »
Just spotted this. I have noticed you're mixing your decimal seperators between "." and ",". Would this happen in the real world?

Here's my quick go based on my parse numbers routine. Apologies for the code formatting, it's straight out of Notepad++
Code: [Select]
(defun rh:regexp ( pattern t_str n_str b1 b2 / regex result matches m_lst rtn)
(if (and (< b2 5) (/= b2 3) (< b1 8))
(progn
(setq regex (vlax-create-object "VBScript.RegExp")
m_lst nil
);_end setq
(vlax-put-property regex 'Pattern pattern)
(if (not b1) (setq b1 0))
(if (/= 0 (boole 1 b1 4)) (vlax-put-property regex 'Multiline :vlax-true)) ;if set TRUE caret and dollar will match each line
(if (/= 0 (boole 1 b1 2)) (vlax-put-property regex 'IgnoreCase :vlax-true)) ;if set TRUE will perform a case-insensitive search
(if (/= 0 (boole 1 b1 1)) (vlax-put-property regex 'Global :vlax-true)) ;if set TRUE = find all matches False = first match

;; Replace Method
(if (/= 0 (boole 1 b2 4))
(progn
(setq result (vlax-invoke-method regex 'Replace t_str n_str))
(vlax-release-object regex)
(setq rtn result)
);_end progn
);_end if

;; Test Method
(if (/= 0 (boole 1 b2 1)) 
(progn
(setq result (vlax-invoke-method regex 'Test t_str))
(vlax-release-object regex)
(setq rtn result)
);_end progn
);_end if

;; Returns a list of matching sub strings if any
(if (/= 0 (boole 1 b2 2))
(progn
(setq matches (vlax-invoke-method regex 'Execute t_str))
(vlax-release-object regex)
(if (> (vlax-get-property matches 'Count) 0)
(progn
(vlax-for item matches
(setq m_lst (cons (vlax-get-property item 'Value) m_lst))
);_end for
(setq rtn (reverse m_lst))
);_end progn
(setq rtn nil)
);_end if
);_end progn
);_end if
);_end progn
);_end if
);_end defun (rh:regexp)


(defun c:test ( / txt r_lst n_lst)
(setq txt "There's 1. week and 1 day till 31/12/2017, so that makes 192.3 hours and 0.5 minutes.")
(setq r_lst (rh:regexp "[^0-9\. ]+|[0-9\.]+" txt "" 3 2))
(if (listp r_lst)
(setq n_lst (mapcar '(lambda (x y) (if (> (atof x) 0) (setq x (if (vl-string-search "." x) (atof x) (atoi x))) (setq x y ))) r_lst r_lst))
)
(princ "\n\n")
(princ n_lst)
)

;;>> ("There's" 1.0 "week" "and" 1 "day" "till" 31 "/" 12 "/" 2017 "," "so" "that" "makes" 192.3 "hours" "and" 0.5 "minutes" ".")


This won't parse numbers in scientific notation i.e. 1.23456E12, and I'm not sure whether you need the spurious punctuation?

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Split String To Strings and Numbers
« Reply #26 on: March 09, 2018, 07:17:21 PM »
Just spotted this. I have noticed you're mixing your decimal seperators between "." and ",". Would this happen in the real world?

In almost all countries of Europe the standard for decimal separator is "," [ISO].
Although there are cases where "." is used and its still accepted, but rather uncommon to use it.
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Dlanor

  • Bull Frog
  • Posts: 263
Re: Split String To Strings and Numbers
« Reply #27 on: March 10, 2018, 04:22:18 AM »
Quote
In almost all countries of Europe the standard for decimal separator is "," [ISO].
Although there are cases where "." is used and its still accepted, but rather uncommon to use it.

I'm aware of that, my point was that the test string contains both "." & "," in locations that indicate they are being used as decimal separators. Any single string of text should be consistant, otherwise your heaping complexity onto a simple function.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Split String To Strings and Numbers
« Reply #28 on: March 10, 2018, 05:49:27 AM »
my point was that the test string contains both "." & "," in locations that indicate they are being used as decimal separators.
Any single string of text should be consistant, otherwise your heaping complexity onto a simple function.

I agree that the text should be consistant, but that doesn't mean it would be - so it doesn't apply on all cases where the #main is used.
For instance:
  • split text patterns from two different projects and compare the values (one uses "." the other ",")
  • split an existing text pattern that breaks the 'consistant rule' (the project was done n-years ago, and you can't trace the author to blame him)
  • use that subfunction within iteration to process n amount of different strings (some use "," other ".")

So I'd rather make it a bit complex, than forcing myself to re-work the correct regex pattern when I'd be short on time.
Ofcourse this problem shouldn't apply to countries like USA if everyone follows the ANSI standard for dot decimal separator.

BTW mentioned from here why you are not passing the literal character, so your regex pattern fails (it splits "Word.AnotherWord") :
Code - Auto/Visual Lisp: [Select]
  1. _$ (SplitStrToStrAndNumbers "Spl.it1.2 thi.s56")                >> ("Spl.it" 1.2 "thi.s" 56)
  2. _$ (rh:regexp "[^0-9\. ]+|[0-9\.]+" "Spl.it1.2 thi.s56" "" 3 2) >> ("Spl" "." "it" "1.2" "thi" "." "s" "56")
  3.  
  4.  
  5. _$ (SplitStrToStrAndNumbers "Word.AnotherWord") >> ("Word.AnotherWord")
  6. _$ (rh:regexp "[^0-9\. ]+|[0-9\.]+" "Word.AnotherWord" "" 3 2) >> ("Word" "." "AnotherWord")

- I still remember MP's valuable advice.
« Last Edit: March 10, 2018, 05:53:44 AM by Grrr1337 »
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Dlanor

  • Bull Frog
  • Posts: 263
Re: Split String To Strings and Numbers
« Reply #29 on: March 10, 2018, 01:02:26 PM »
BTW mentioned from here why you are not passing the literal character, so your regex pattern fails (it splits "Word.AnotherWord") :

Which literal character? The regex used was a quick adaptation of a regex used to extract integer and real numbers from a text string.

I have adapted the regex and incorporated some look forwards.
Code: [Select]
(rh:regexp "[0-9\.]+|(?:[A-Za-z\.(?!\d)\/(?=\d)]+)|[\,]" txt "" 3 2)


txt = Spl.it1.2 thi.s56
 >> ("Spl.it" 1.2 "thi.s" 56)

txt = Word.AnotherWord 
>> ("Word.AnotherWord")

txt = "Theres 1. week and 1 day till 31/12/2017, so that makes 192.3 hours and 0.5 minutes."
>> ("Theres" 1.0 "week" "and" 1 "day" "till" 31 "/" 12 "/" 2017 "," "so" "that" "makes" 192.3 "hours" "and" 0.5 "minutes.")

I'm not sure in the last string whether the comma (",") after 2017 is used as a decimal separator or a comma. I've assumed comma as it makes more sense when you read it.