如何在mapcar中指定替换参数?

时间:2016-04-23 18:01:53

标签: lisp common-lisp

例如,我有一个"字符串列表" :(" First"" second"" third。")。
我需要更换所有" s"到" a" - > (("的Firat&#34)...等 我发现了非常漂亮的功能,称为替代,但它只适用于一个序列 我可以在mapcar中使用替代品吗?这样的事情:

(mapcar 'substitute #\d #\o '(("test") ("wow") ("waow")))

3 个答案:

答案 0 :(得分:6)

您可以在函数周围包裹LAMBDA

(mapcar (lambda (string) (substitute #\d #\o string)) '("test" "wow" "waow"))
;=> ("test" "wdw" "wadw")

或者您可以使用名为CURRY的辅助函数(它不是Common Lisp标准的一部分,但可以在Alexandria中使用)。

(ql:quickload :alexandria)
(use-package :alexandria)
(mapcar (curry #'substitute #\d #\o) '("test" "wow" "waow"))
;=> ("test" "wdw" "wadw")

对于子列表中的多个字符串,您可以使用嵌套的mapcar / lambda:

(mapcar (lambda (sentence) 
          (mapcar (lambda (string) 
                    (substitute #\d #\o string))
                  sentence))
        '(("I" "like" "my" "dog.") ("My" "dog" "likes" "me" "too.")))
;=> (("I" "like" "my" "ddg.") ("My" "ddg" "likes" "me" "tdd."))

内部LAMBDA也可以更改为CURRY

(mapcar (lambda (sentence) 
          (mapcar (curry #'substitute #\d #\o) sentence))
        '(("I" "like" "my" "dog.") ("My" "dog" "likes" "me" "too.")))

甚至:

(mapcar (curry #'mapcar (curry #'substitute #\d #\o))
        '(("I" "like" "my" "dog.") ("My" "dog" "likes" "me" "too.")))

答案 1 :(得分:4)

我添加了jkiiski非常好的回答在这种情况下指定substitute的参数的最后可能性,尽管它可能不是你需要的:

(mapcar #'substitute '(#\x #\x #\x) '(#\a #\b #\c) '("abcd" "abcd" "abcd"))
;; => ("xbcd" "axcd" "abxd")

此处对于任何传递列表的最低长度imapcar将第一个列表的i元素作为第一个参数传递,i第二个元素作为第二个参数,i个元素作为substitute的第三个参数。这是有效的,因为mapcar需要一个或任意数量的列表。

只有在(几乎)每个字符串上执行不同的替换时才使用它。

答案 2 :(得分:2)

除了平面列表之外,可以考虑递归,以处理一般的嵌套情况:

(labels ((my-sub (s)
           (typecase s
             (string (substitute #\d #\o s))
             (list (mapcar #'my-sub s))
             (otherwise s))))
  (my-sub '(("I" "like" "my" "dog.")
        ("My" ("dog" "likes" "me") "too."))))