Hey everyone,
I am trying to convert a string, such as "AAAA,BBBB,CCCC,DDDD,EEEE" into a list using the commas as a delimiter. I have been using the following code (not written by me):
;----------------------------------------------------------------------
;
; STR-2-LIST
; SRC source string
; DLM delimiter
;
(defun STR-2-LIST (SRC DLM)
(read
(strcat
"(" (chr 34)
(STRREPL-ALL SRC DLM (strcat (chr 34) " " (chr 34)))
(chr 34) ")")))
;
;;---------------------------------------------------------------------
;RC String to search
;SRCH String pattern to find
;
(defun STRFIND (SRC SRCH / CNT RET)
(setq CNT 1)
(while (<= CNT (strlen SRC))
(if
(= (substr SRC CNT (strlen SRCH)) SRCH)
(setq RET (list
(substr SRC 1 (1- CNT))
(substr SRC (+ CNT (strlen SRCH))))
CNT (1+ (strlen SRC)))
(setq CNT (1+ CNT))))
(if (null RET) (list SRC nil) RET))
;----------------------------------------------------------------------
;
; STRREPL
; SRC source string
; SRCH string to find
; SREP replacement string
;
(defun STRREPL (SRC SRCH SREP / TMP)
(setq TMP (STRFIND SRC SRCH))
(if (not (null (cadr TMP))) (strcat (car TMP) SREP (cadr TMP)) SRC))
;----------------------------------------------------------------------
;
; STRREPL-ALL
; SRC source string
; SRCH string to find
; SREP replacement string
;
(defun STRREPL-ALL (SRC SRCH SREP)
(while (/= SRC (setq SRC (STRREPL SRC SRCH SREP))))
SRC)
This works fine for small lists, but some lists I am working with can contain 1500 entries which can take over 10 seconds for the above code to convert from the string to a list. This time really starts to add up (and become annoying) when you have to run this command many times in succession.
Does anyone have any ideas for alternate code that is less demanding on the computer?
Thanks as always for your help,
Chris
Solved! Go to Solution.
Solved by Hallex. Go to Solution.
;;author unknown (defun strtolst (str del) (if (setq pos (vl-string-search del str)) (cons (substr str 1 pos) strtolst (substr str (+ pos 1 (strlen del))) del)) (list str) ) )
~'J'~
hallex, that doesn't seem correct.
Perhaps sometging like this will suit :
(defun CSVString->List (str del / i lst) (while (setq i (vl-string-search del str 0)) (setq lst (cons (substr str 1 i) lst) str (substr str (+ i 1 (strlen del))) ) ) (reverse (cons str lst)) )
// Called Kerry in my other life.
Everything will work just as you expect it to, unless your expectations are incorrect.
class keyThumper<T> : Lazy<T>; another Swamper
Oops, missed the open parenthesis, sorry
This should work
(defun strtolst (str del) (if (setq pos (vl-string-search del str)) (cons (substr str 1 pos) (strtolst (substr str (+ pos 1 (strlen del))) del)) (list str) ) )
~'J'~
Some other ways of doing it:
And a Search will reveal other similar threads.
This might be faster on larger strings:
(defun string-to-list (s) (read (strcat "(\"" (vl-list->string (apply 'append (subst '(34 34) '(44) (mapcar 'list (vl-string->list s)) ) ) ) "\")" ) ) )
Hi Tony,
If I'm not the author of this routine, I wrote a very similar one (called str2lst with others variables names).
I agree (strlen del) is contant, but as the routine uses a recursive process in which the expression is evaluated at each recursive call, I thaught unusefull to stroe the value in a variable.
Another way [not better, not shorter, but not much longer than some others] that it occurred to me that this can be done, as long as the delimiter is a single character:
(defun StrToList (s d / c w r)
(setq w "")
(while (> (strlen s) 0)
(if (/= (setq c (substr s 1 1)) d)
(setq w (strcat w c))
(setq r (cons w r) w "")
)
(setq s (substr s 2))
)
(reverse (cons w r))
)
[The s is for string, d for delimiter, c for character, w for word, r for result.]
It steps through the string, and if the next character is not the delimiter, it adds it to the word it is building, but if it is the delimiter, it adds the word it has built so far to the result list. When it gets to the end, it adds the last word it has built, in the process of reversing the list.
If the quest was for the most efficent way, then using an approach
involving a (strcat) for each character added to each string would not
be terribly efficient, because each (strcat) must create a copy of the
original string, which generates a lot of garbage. Of course it wouldn't
matter much in cases where the strings being built are small, or there
there are not very many of them, but in other cases, depending mainly
on the number of calls to (strcat), it could be noticable.
Have a look at this:
Can't find what you're looking for? Ask the community or share your knowledge.