Skip to content

Instantly share code, notes, and snippets.

@lispm
Last active December 11, 2016 17:52
Show Gist options
  • Save lispm/71fa971416307905b9c2b7a2beee55e9 to your computer and use it in GitHub Desktop.
Save lispm/71fa971416307905b9c2b7a2beee55e9 to your computer and use it in GitHub Desktop.
; https://github.com/alandipert/dotfiles/blob/master/dotfiles/bash/abbrev_pwd.lisp
; original
; splits string into a vector of strings
(defun split-string (str delim-char)
(let* ((num-delims 2)
(delim-idxs (loop with idxs = (list (length str))
for idx from (1- (length str)) downto 0
when (eq (elt str idx) delim-char)
do (setq idxs (cons idx idxs)
num-delims (1+ num-delims))
finally (return (cons -1 idxs)))))
(loop with parts = (make-array (1- num-delims) :fill-pointer 0)
for idxs on delim-idxs by #'cdr
for (x y) = idxs
when y
do (vector-push (subseq str (1+ x) y) parts)
finally (return parts))))
; list-based version
; splits a vector into a list of strings
(defun character-indices (string character)
"Returns a list of indices where the character occurs in the string"
(loop for element across string and index from 0
when (eql element character)
collect index))
(defun split-string (string delim-char)
"Returns a list of strings, split at the delimiter character.
For delimiter character at the beginning or the end of the string,
an empty string is collected in the result."
(loop for (x y) on (cons -1 (character-indices string delim-char))
collect (subseq string
(1+ x)
(or y (length string)))))
; function from above using CHAR accessor
(defun character-indices (string character)
(loop for i below (length string)
when (eql (char string i) character)
collect i))
; using POSITION to find the characters
(defun split-string (string delim-char)
(loop for (x y) on (loop for pos = -1 then (position delim-char string :start (1+ pos))
collect (or pos (length string))
while pos)
while y
collect (subseq string (1+ x) y)))
;;; do it all in one LOOP using POSITION
; advantages over the original:
; * shorter code
; * less variables
; * no custom collection operations
; * left to right processing
; * no intermediate list
; * no nested LOOPs
(defun split-string (string delim-char)
(loop for pos0 = -1 then pos1
for pos1 = (position delim-char string :start (1+ pos0))
collect (subseq string (1+ pos0) (or pos1 (length string)))
while pos1))
; the above in old-style Lisp using DO*
(defun split-string (string delim-char &aux result)
(do* ((pos0 -1 pos1)
(pos1 (position delim-char string)
(and pos0 (position delim-char string :start (1+ pos0)))))
((not pos0) (nreverse result))
(push (subseq string (1+ pos0) (or pos1 (length string)))
result)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment