Aro*_*oob 1 functional-programming common-lisp
假设您有一个列表列表,例如'(("abc" "def" "ghi") ("012" "345" "678") ("jkl" "mno" "pqr"))或'(("ab" "cd" "ef") ("01" "23" "45")).
压缩给定列表中列表的规范方法是什么?即如何func定义如此
(func '(("ab" "cd" "ef") ("01" "23" "45")) :sep "|" :combiner #'concat)
;; => ("ab|01" "cd|23" "ef|45")
(func '(("abc" "def" "ghi") ("012" "345" "678") ("jkl" "mno" "pqr")) ...)
;; => ("abc|012|jkl" "def|345|mno" "ghi|678|pqr")
Run Code Online (Sandbox Code Playgroud)
哪个concat := (lambda (args) ...)是组合各个列表的头部的功能.
据推测,这种类型的操作被称为旋转或zipMany(根据不同语言的相关问题的答案).
我有类似的东西(双apply)
(apply #'mapcar #'(lambda (&rest args) (apply #'concatenate 'string args)) lst)
Run Code Online (Sandbox Code Playgroud)
其中lst是'(("ab" "cd" "ef") ("01" "23" "45"))
例如.该combiner会concatenate.请注意,此示例实现中未给出分隔符.
但这似乎非常令人费解.
那么,这种操作的规范实现是什么?
对于任意数量的列表,您需要摆脱apply #'mapcar,否则列表的数量将受到限制call-arguments-limit.
一种典型的方法是使用reduce,一次组合两个列表:
(defun zip (list-of-lists &key (combiner #'concat))
(reduce (lambda (list-a list-b)
(mapcar combiner list-a list-b))
list-of-lists))
Run Code Online (Sandbox Code Playgroud)
如果您不喜欢显式lambda表单,您可能会喜欢curry,例如alexandria:
(defun zip (list-of-lists &key (combiner #'concat))
(reduce (curry #'mapcar combiner)
list-of-lists))
Run Code Online (Sandbox Code Playgroud)
其他循环结构是loop,do,dolist,,也有几个循环的库,例如iterate,for.
加入
(defun %d (stream &rest args)
"internal function, writing the dynamic value of the variable
DELIM to the output STREAM. To be called from inside JOIN."
(declare (ignore args)
(special delim))
(princ delim stream))
(defun join (list delim)
"creates a string, with the elements of list printed and each
element separated by DELIM"
(declare (special delim))
(format nil "~{~a~^~/%d/~:*~}" list))
Run Code Online (Sandbox Code Playgroud)
目标
不要使用&restargs 或apply- 这会限制我们的列表长度。
递归MAPCARS
(defun mapcars (f l)
(if (null (car l))
'()
(cons (funcall f (mapcar #'car l))
(mapcars f (mapcar #'cdr l)))))
Run Code Online (Sandbox Code Playgroud)
迭代MAPCARS
(defun mapcars (f l)
(loop for l1 = l then (mapcar #'cdr l1)
while (car l1)
collect (funcall f (mapcar #'car l1))))
Run Code Online (Sandbox Code Playgroud)
用法
CL-USER 10 > (mapcars (lambda (l) (join l "|")) l)
("abc|012|jkl" "def|345|mno" "ghi|678|pqr")
Run Code Online (Sandbox Code Playgroud)