如何从普通 lisp 中的列表列表中获取列表
how to get a list out of list of lists in common lisp
我是普通 lisp 的新手,正在尝试从拆分的字符串中获取列表。
例如:
["4-无 16dia","6-无 20dia"]
现在我只想收集第三个元素,如 ["16","20"]
我已经正确地使用了拆分部分:
(defun my-split (string &key (delimiterp #'delimiterp)
)
(loop :for beg = (position-if-not delimiterp string)
:then (position-if-not delimiterp string :start (1+ end)
)
:for end = (and beg (position-if delimiterp string :start beg))
:when beg :collect (subseq string beg end)
:while end))
其中:
(defun delimiterp (c) (position c " ,-:"))
但只将第三个元素收集到列表中是棘手的部分,我已经尝试过:
(defparameter *list1*
(loop for i in (cdr list)
(append (parse-integer
(nth 0
(my-split (nth 3 i)
:delimiterp #'delimiterp))))))
P.S:有两个列表 cz 示例字符串本身是列表列表的一部分
请帮助我,提前致谢
我会使用正则表达式,而且我认为我会在很大程度上不考虑我使用的语言。当然,有些语言没有正则表达式,但有了正则表达式就省得重新造轮子了。
在Common Lisp中,正则表达式库叫做Common Lisp - Practical Perl Compatible Regular Expressions,cl-ppcre。我们用 (ql:quickload "cl-ppcre")
.
加载它
然后可以使用 (ppcre:scan-to-strings "^(\d*)-No (\d*)dia$" x)
对数字进行 return 编辑。正则表达式使用 \d
来挑选一个数字,在 Lisp 字符串中写成 \d
。星号表示 return 零个或多个数字。正则表达式中的括号是我们要 return 的位,即数字。
对字符串列表执行此操作只需使用 mapcar
.
(defparameter text-match "")
(defparameter text-numbers "")
(defparameter test-text '("4-No 16dia" "6-No 23dia"))
(defun extract-numbers (text)
(setf (values text-match text-numbers)
(ppcre:scan-to-strings "^(\d*)-No (\d*)dia$" text))
text-numbers)
(defun extract-numbers-from-list (lst)
(mapcar #'extract-numbers lst))
(extract-numbers-from-list test-text) ; => (#("4" "16") #("6" "23"))
编辑:词汇绑定
当我写上面的内容时,我试图让正则表达式正确,同时试图让词法绑定正确。由于时间有限,我努力使正则表达式正确,并使用了动态变量和 setf。好的,它完成了工作,但我们可以做得更好。
经典的词法绑定系统是let
,句法(let ( (var1 val1) (var2 val2) ...) body)
。我们可以尝试 (let ((x 0)))
,这是有效的 Lisp 代码,但作用不大。一旦词法作用域结束,变量 x
就被解除绑定。尝试访问 x
会导致错误。
我们可以 return 来自许多函数的多个值,例如 floor
或 scan-to-string
。我们现在必须使用 (multiple-value-bind (variable-list) values)
将这些值绑定到变量。大多数网站并没有很好地解释这一点。绑定变量后,我收到有关未绑定变量的错误。好的,值得一提的是 -
multiple-value-bind
词法绑定变量,就像 let
.
完整的语法是 (multiple-value-bind (variable-list) values body)
,您的代码进入正文部分,就像 let
一样。因此上面的代码变成:
(defparameter test-text '("4-No 16dia" "6-No 23dia"))
(defun extract-numbers (text)
(multiple-value-bind (text-match text-numbers)
(ppcre:scan-to-strings "^(\d*)-No (\d*)dia$" text)
text-numbers))
(defun extract-numbers-from-list (lst)
(mapcar #'extract-numbers lst))
(extract-numbers-from-list test-text) ; => (#("4" "16") #("6" "23"))
没有依赖项,可以使用:
(defun extract-nums (s)
(mapcar #'(lambda (x) (parse-integer x :junk-allowed t))
(ql-util:split-spaces s)))
并尝试使用:
(defparameter *s* (list "4-No 16dia" "6-No 20dia"))
(mapcar #'extract-nums *s*)
;; => ((4 16) (6 20))
parse-integer
设置 junk-allowed-p t
有助于从字符串中提取整数。
但是,是的,在现实生活中我也会使用 cl-ppcre
,例如
主要是函数 cl-ppcre:split
和 cl-ppcre:scan-to-strings
.
(ql:quickload :cl-ppcre)
(defun extract-nums (s)
(mapcar #'parse-integer (cl-ppcre:scan-to-strings "(\d+)-No (\d+)dia" s))
从那以后就是
(second (map #'list (mapcar #'extract-nums *s*))
;; => (16 20)
补充一下,cl-ppcre
也有 register-groups-bind
以单一形式进行正则表达式匹配、绑定和转换:
CL-USER> (cl-ppcre:register-groups-bind ((#'parse-integer no dia))
("(\d+)-No (\d+)dia" "4-No 16dia")
(values no dia))
4
16
我是普通 lisp 的新手,正在尝试从拆分的字符串中获取列表。 例如: ["4-无 16dia","6-无 20dia"] 现在我只想收集第三个元素,如 ["16","20"] 我已经正确地使用了拆分部分:
(defun my-split (string &key (delimiterp #'delimiterp)
)
(loop :for beg = (position-if-not delimiterp string)
:then (position-if-not delimiterp string :start (1+ end)
)
:for end = (and beg (position-if delimiterp string :start beg))
:when beg :collect (subseq string beg end)
:while end))
其中:
(defun delimiterp (c) (position c " ,-:"))
但只将第三个元素收集到列表中是棘手的部分,我已经尝试过:
(defparameter *list1*
(loop for i in (cdr list)
(append (parse-integer
(nth 0
(my-split (nth 3 i)
:delimiterp #'delimiterp))))))
P.S:有两个列表 cz 示例字符串本身是列表列表的一部分 请帮助我,提前致谢
我会使用正则表达式,而且我认为我会在很大程度上不考虑我使用的语言。当然,有些语言没有正则表达式,但有了正则表达式就省得重新造轮子了。
在Common Lisp中,正则表达式库叫做Common Lisp - Practical Perl Compatible Regular Expressions,cl-ppcre。我们用 (ql:quickload "cl-ppcre")
.
然后可以使用 (ppcre:scan-to-strings "^(\d*)-No (\d*)dia$" x)
对数字进行 return 编辑。正则表达式使用 \d
来挑选一个数字,在 Lisp 字符串中写成 \d
。星号表示 return 零个或多个数字。正则表达式中的括号是我们要 return 的位,即数字。
对字符串列表执行此操作只需使用 mapcar
.
(defparameter text-match "")
(defparameter text-numbers "")
(defparameter test-text '("4-No 16dia" "6-No 23dia"))
(defun extract-numbers (text)
(setf (values text-match text-numbers)
(ppcre:scan-to-strings "^(\d*)-No (\d*)dia$" text))
text-numbers)
(defun extract-numbers-from-list (lst)
(mapcar #'extract-numbers lst))
(extract-numbers-from-list test-text) ; => (#("4" "16") #("6" "23"))
编辑:词汇绑定
当我写上面的内容时,我试图让正则表达式正确,同时试图让词法绑定正确。由于时间有限,我努力使正则表达式正确,并使用了动态变量和 setf。好的,它完成了工作,但我们可以做得更好。
经典的词法绑定系统是let
,句法(let ( (var1 val1) (var2 val2) ...) body)
。我们可以尝试 (let ((x 0)))
,这是有效的 Lisp 代码,但作用不大。一旦词法作用域结束,变量 x
就被解除绑定。尝试访问 x
会导致错误。
我们可以 return 来自许多函数的多个值,例如 floor
或 scan-to-string
。我们现在必须使用 (multiple-value-bind (variable-list) values)
将这些值绑定到变量。大多数网站并没有很好地解释这一点。绑定变量后,我收到有关未绑定变量的错误。好的,值得一提的是 -
multiple-value-bind
词法绑定变量,就像 let
.
完整的语法是 (multiple-value-bind (variable-list) values body)
,您的代码进入正文部分,就像 let
一样。因此上面的代码变成:
(defparameter test-text '("4-No 16dia" "6-No 23dia"))
(defun extract-numbers (text)
(multiple-value-bind (text-match text-numbers)
(ppcre:scan-to-strings "^(\d*)-No (\d*)dia$" text)
text-numbers))
(defun extract-numbers-from-list (lst)
(mapcar #'extract-numbers lst))
(extract-numbers-from-list test-text) ; => (#("4" "16") #("6" "23"))
没有依赖项,可以使用:
(defun extract-nums (s)
(mapcar #'(lambda (x) (parse-integer x :junk-allowed t))
(ql-util:split-spaces s)))
并尝试使用:
(defparameter *s* (list "4-No 16dia" "6-No 20dia"))
(mapcar #'extract-nums *s*)
;; => ((4 16) (6 20))
parse-integer
设置 junk-allowed-p t
有助于从字符串中提取整数。
但是,是的,在现实生活中我也会使用 cl-ppcre
,例如
主要是函数 cl-ppcre:split
和 cl-ppcre:scan-to-strings
.
(ql:quickload :cl-ppcre)
(defun extract-nums (s)
(mapcar #'parse-integer (cl-ppcre:scan-to-strings "(\d+)-No (\d+)dia" s))
从那以后就是
(second (map #'list (mapcar #'extract-nums *s*))
;; => (16 20)
补充一下,cl-ppcre
也有 register-groups-bind
以单一形式进行正则表达式匹配、绑定和转换:
CL-USER> (cl-ppcre:register-groups-bind ((#'parse-integer no dia))
("(\d+)-No (\d+)dia" "4-No 16dia")
(values no dia))
4
16