lisp中delete-duplicates中参数key的含义

 (setq tester (list 0 1 2 3 4 5 6))
 (delete-duplicates tester :key #'oddp :start 1 :end 6) =>  (0 4 5 6)

请问这个示例中key的含义是什么? 文档参考链接 http://clhs.lisp.se/Body/f_rm_rm.htm http://clhs.lisp.se/Body/f_rm_dup.htm

去重的时候需要不断对比两个数据是否相同。有时你只需要两个数据在某一方面相同,就先用 key 函数变换一下,提取出你需要的那方面

;; 比如只要两个 pair 的 car 部分相同就等价
(setq tester '((1 2) (1 3) (0 2)))
(delete-duplicates tester :key #'car) => ((1 3) (0 2))
;; https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node144.html
;; 只要 pair 后半部分的 char 相同就等价
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A)) 
                   :test #'char-equal :key #'cadr) 
   => ((bar #\%) (baz #\A)) 

(remove-duplicates '((foo #\a) (bar #\%) (baz #\A)) 
                   :test #'char-equal :key #'cadr :from-end t) 
   => ((foo #\a) (bar #\%))

但是楼主给的这个例子很有意思,依赖一些细节才输出 (0 4 5 6)

:start 1 :end 6 的 start 是包含的,end 是不包含的,

所以去重的只有 (1 2 3 4 5),0 和 6 是不变的

delete-duplicates 会优先保留相同元素中靠右的那个(上面例子里面的 :from-end t 会逆转这个行为)

(1 2 3 4 5) 加上 :key #'oddp 会变成 (t f t f t),对应位置去重 (保留最右边 f t 对应的元素),并优先保留右边就变成了 (4 5)

然后结果就是 (0 4 5 6)


这种依赖细节的东西,盲猜是学校的作业或课件什么的,藏着点东西阴一下不学的,作为例子感觉不合适。

4 个赞

如果没有 :start :end 列表就会变成 (0 1 2 3 4 5 6) => (NIL T NIL T NIL T NIL) 去重,只保留最后两个 T NIL 也就是 (5 6) 了

(setq tester (list 0 1 2 3 4 5 6))
(delete-duplicates tester :key #'oddp) => (5 6)
1 个赞

RMS 嫌弃 CL 里面各种带 keyword 的函数不是没有道理的

描述非常具体,多谢你的详细回复哈!