
Common Lisp - String parsing
Quote:
> I want to parse strings like "hello world" into a list containing all the
> words: ("hello" "world").
> How could I do this?
;;From CLOCC's string.lisp
(defun split-seq (seq pred &key (start 0) end key strict)
"Return a list of subseq's of SEQ, split on predicate PRED.
Start from START, end with END. If STRICT is non-nil, collect
zero-length subsequences too.
(split-seq SEQ PRED &key (start 0) end key strict)"
(declare (sequence seq) (type (function (t t) t) pred) (fixnum start))
(loop :for st0 = (if strict start
(position-if-not pred seq :start start
:end end :key key))
:then (if strict (if st1 (1+ st1))
(position-if-not pred seq :start (or st1 st0)
:end end :key key))
:with st1 = 0 :while (and st0 st1) :do
(setq st1 (position-if pred seq :start st0 :end end :key key))
:collect (subseq seq st0 st1)))
(defun split-string (str chars &rest opts)
"Split the string on chars."
(declare (string str) (sequence chars))
(apply #'split-seq str (lambda (ch) (declare (character ch)) (find ch chars))
opts))
;;Simpler version using loop
(defun split-string-2 (string &optional (separator #\Space))
(loop for i = 0 then (1+ j)
as j = (position separator string :start i)
collect (subseq string i j) while j))
;;Same as above, but with do* instead of loop
(defun split-string-3 (string &optional (separator #\Space))
(do* ((i 0 (1+ j))
(j (position separator string :start i) (position separator string :start i))
(words (list (subseq string i j)) (push (subseq string i j) words)))
((null j) (nreverse words))))
CL-USER(11): (split-string "hello world" '(#\Space))
("hello" "world")
CL-USER(12): (split-string-2 "hello world")
("hello" "world")
CL-USER(13): (split-string-3 "hello world")
("hello" "world")