解决方案
既然你不理解亚历山大的解决方案,而且我还是写了我的解决方案:
;; load two essential libraries for any common lisper
(ql:quickload :cl-ppcre)
(ql:quickload :alexandria)
;; see below to see how to install quicklisp for `ql:quickload` command
;; it is kind of pythons `import` and if not install `pip install`
;; in one command for common-lisp
(defun remove-empty-string (string-list)
(remove-if #'(lambda (x) (string= x "")) string-list))
(defun split-parantheses-and-preserve-them (strings-list)
(remove-empty-string
(alexandria:flatten
(mapcar #'(lambda (el) (cl-ppcre:split "(\\(|\\))"
el
:with-registers-p t))
strings-list))))
;; so now your example
(defparameter *list* '("(aviyon" "213" "flyingman" "no))"))
(split-parantheses-and-preserve-them *list*)
;; returns:
;; ("(" "aviyon" "213" "flyingman" "no" ")" ")")
这是如何工作的
(cl-ppcre:split "(\\(|\\))" a-string)
(
用or
分割字符串)
。因为在正则表达式模式中(
或)
用于捕获匹配 - 就像这里一样(外部括号捕获) - 你必须逃避它们。\\(
或\\)
。因此,cl-ppcre:split
您可以通过正则表达式模式拆分普通 lisp 中的任何字符串。由 Edi Weitz 编写的超酷且超高效的软件包。他为 common lisp 编写了几个超级复杂的包——它们在社区中也被称为 ediware 或 edicls。顺便说一句 - cl-ppcre 比正则表达式的黄金标准:perl 正则表达式引擎更高效、更快!
:with-regiesters-p t
然后选项保留匹配的分隔符 - 必须通过括号捕获,如下所示:(<pattern>)
在模式中。
mapcar
this 在列表上以将其应用于字符串列表中的每个字符串元素。
但是,之后得到的是列表列表。(每个内部列表都包含列表中每个字符串元素的拆分结果)。
将列表展平alexandria:flatten
。对于许多不在 lisp 标准中的函数,但您认为它们是基本的——比如展平列表——总是首先在亚历山大港中查找——大多数情况下它有你想要的函数——它是一个巨大的库。这就是为什么你无论如何都需要它作为一个普通的 lisper ;) 。
但是,仍然会有空字符串被删除。这就是为什么我写了remove-empty-string
which uses remove-if
- which 以及remove-if-not
列表的标准过滤功能。它需要一个谓词函数 -(lambda (x) (string= x ""))
如果字符串为空字符串,则为 T,否则为 NIL。它删除了我们函数中生成的扁平列表中的所有元素,这些元素是空字符串。在其他语言中,它会被命名filter
,但是是的 - 有时 common-lisp 中的函数名称选择得不是很好。有时我认为我们应该创建别名并转移到它们并保留旧名称以实现向后兼容性。Clojure 有更好的函数名称......也许 cl 人应该超越 clojure 函数名称......
快捷方式
@Alexander Artemenko 写的正是我的解决方案——他是第一位的。我要补充一点:如果您对 common lisp 很陌生,也许您不知道如何使用 quicklisp。在终端(linux或macos)中执行:
wget https://beta.quicklisp.org/quicklisp.lisp
否则从地址手动在windows中下载。
我把它放在~/quicklisp
文件夹里。
然后在 clisp 或 sbcl 中执行:
(load "~/quicklisp/quicklisp.lisp") ;; just path to where downloaded
;; quicklisp.lisp file is!
;; then install quicklisp:
(quicklisp-quickstart:install)
;; then search for cl-ppcre
(ql:system-apropos "cl-ppcre")
;; then install cl-ppcre
(ql:quickload "cl-ppcre")
;; and to autoload everytime you start sbcl or clisp
;; in linux or mac - sorry I don't now windows that well
;; I have the opinion every programmer should us unix
;; as their OS
;; you have to let quicklisp be loaded when they start
;; by an entry into the init file
;; mostly located in ~/.sbclrc or ~/.clisprc.slip or such ...
;; respectively.
;; quicklisp does an entry automatically if you do:
(ql:add-to-init-file)
;; after installation do:
(quit)
;; If you then restart sbcl or clisp and try:
(ql:quickload :cl-ppcre)
;; it should work, - if not, you have to manually load
;; quicklisp first
(load "~/quicklisp/setup.lisp") ;; or wherever quicklisp's
;; setup.lisp file has been stored in your system!
;; and then you can do
(ql:quickload :cl-ppcre)
;; to install alexandria package then, do
(ql:quickload :alexandria) ;; or "alexandria"
;; ql:quickload installs the package from quicklisp repository,
;; if it cannot find package on your system.
;; learn more about quicklisp, since this is the package
;; manager of common lisp - like pip for python