Separate string into lists

Separate string into lists

Anonymous
Not applicable
2,371 Views
4 Replies
Message 1 of 5

Separate string into lists

Anonymous
Not applicable

Hi!

I've a CSV file whose each line is a list of attributes I have to insert in a determinate block. This is one example: 

NameValue 1Value 2 Value 3 
NameValue 1Value 2 Value 3Value 4
Name Value 1Value 2   

 

Let me explain: Block's type is given at the first column and the remainder columns are the attribute values I've to read. Not every type of block have the same number of attributes...

I've done something like that:

 

setq f (open "C:\\Users\\User\\Documents\\MyCSV.csv" "r"))
(while (setq txtline(read-line f))
  (princ txtline)
  (princ "\n")
)

And I get txtline as a String similar to: Name;Value 1;Value 2;Value 3 and so on. Now, What I need is split this string and convert it into a list so my final list must be equal to this (for the first row): (list "Name" "Value 1" "Value 2" "Value 3")

I don't know how to do this. I belive it's a simple task but I can't do it

Thank you

 

0 Likes
Accepted solutions (1)
2,372 Views
4 Replies
Replies (4)
Message 2 of 5

DannyNL
Advisor
Advisor
Accepted solution

Think there are lot of examples already on how to do this, but this is my old piece of code that I use to split strings into lists.

 

(defun String2List (S2L_String S2L_Delimiter / S2L_Return S2L_End S2L_EndPos S2L_Item)
  (setq S2L_End nil)
  (while
     (and
        (setq S2L_EndPos (vl-string-search S2L_Delimiter S2L_String))
        (not S2L_End)
     )
     (if
        S2L_EndPos
        (progn
	   (setq S2L_Item (substr S2L_String 1 S2L_EndPos))
	   (setq S2L_Return (append S2L_Return (list S2L_Item)))
	   (setq S2L_String (substr S2L_String (+ S2L_EndPos 2)))
        )
        (setq S2L_End T)
     )   
  )
  (if
     (/= S2L_String "")
     (setq S2L_Return (append S2L_Return (list S2L_String)))
  )
  S2L_Return  
)

So in your case it would be the code below to split the string into the required list.

(String2List txtline ";")

 

0 Likes
Message 3 of 5

martti.halminen
Collaborator
Collaborator

Here's a recursive splitting function:

(defun split-at (char str / pos  )
  ;; Splits string to a list of strings at each char occurrence.
  ;; Separators omitted from the result.
  ;; char as an one-character string.
  (setq pos (vl-string-position (ascii char) str))
  (cond
    ((or (null char) (null str)) nil)
    ((null pos) (list str))
    (T (cons (substr str 1 pos)
             (split-at char (substr str (+ 2 pos)))))))

-- 

0 Likes
Message 4 of 5

DannyNL
Advisor
Advisor

Yes, I would definitely go for recursive as well now.

But I wrote the code many many years ago, before even considering recursive programming. Things have changed however.

 

So I've rewritten my old code now to be more fool proof and recursive. As an added bonus the text delimiter can now be any string and doesn't need to be only one character, although for the purpose of splitting strings from a CSV file it doesn't have any added value.

(defun String2List (S2L_String S2L_Delimiter / S2L_Found)
   (cond
      (
         (or                        
            (/= (type S2L_String)    'STR)
            (/= (type S2L_Delimiter) 'STR)  
         )
         nil
      )
      (
         (or
            (= S2L_Delimiter "")
            (not (setq S2L_Found (vl-string-search S2L_Delimiter S2L_String)))
         )
         (list S2L_String)
      )
      (
         T
         (cons (substr S2L_String 1 S2L_Found) (String2List (substr S2L_String (+ S2L_Found (1+ (strlen S2L_Delimiter)))) S2L_Delimiter))
      )
   )
)

 

0 Likes
Message 5 of 5

john.uhden
Mentor
Mentor

You might like this version...

;;-------------------------------------------------------------
;; This function takes a delimited string, and returns a list:
;;------------------------------
;;Don: (02-09-02)
;;
;;First let me point out that the one you call JohnU is actually
;;Marc'Antonio's from November.
;;
;;As Marc'Antonio sagely reminded us, setting string symbols is slower than
;;setting integers.
;;
;;Your offering is the almost the same a Luis' except that yours doesn't
;;provide for validating the input or for multiple-character delimiters.
;;
;;While Marc'Antonio's method is the fastest, I've grown a liking to the
;;multiple-character delimiter, which his will not handle.
;;
;;Taking the best from Luis and Marc'Antonio, plus acknowledgments to Eric
;;Schneider, I now offer the following...
(defun @cv_str2list (str pat / i j n lst)
  (cond
    ((/= (type str)(type pat) 'STR))
    ((= str pat)'(""))
    (T
      (setq i 0 n (strlen pat))
      (while (setq j (vl-string-search pat str i))
        (setq lst (cons (substr str (1+ i)(- j i)) lst)
              i (+ j n)
        )
      )
      (reverse (cons (substr str (1+ i)) lst))
    )
  )
)
;; It's not as fast as Marc'Antonio's, but pretty close.

John F. Uhden

0 Likes