给出一个列表如
(list "foo" "bar" nil "moo" "bar" "moo" nil "affe")
Run Code Online (Sandbox Code Playgroud)
如何构建一个新的列表,删除重复的字符串,以及nil剥离的,即
(list "foo" "bar" "moo" "affe")
Run Code Online (Sandbox Code Playgroud)
需要保留元素的顺序 - 可能不会删除字符串的第一个出现.
我在这里处理的列表很短,所以不需要像哈希表那样使用任何东西进行唯一性检查,尽管这样做肯定也不会受到影响.但是,使用cl功能不是一个可行的选择.
sco*_*zer 35
尝试使用Emacs Lisp参考手册的"列表"部分中的"设置和列表":
(delq nil (delete-dups (list "foo" "bar" nil "moo" "bar" "moo" nil "affe")))
Run Code Online (Sandbox Code Playgroud)
Gil*_*il' 16
在Common Lisp的包包含许多列表操作功能,尤其是remove-duplicates.
(require 'cl)
(remove-duplicates (list "foo" "bar" nil "moo" "bar" "moo" nil "affe")
:test (lambda (x y) (or (null y) (equal x y)))
:from-end t)
Run Code Online (Sandbox Code Playgroud)
是的,我意识到你说你不想用cl.但是我仍然提到这是为其他可能阅读这个帖子的人做这件事的正确方法.
(为什么cl对你来说不可行?它已经与Emacs一起发售了大约20年,不计算过去的化身特征.)
如果您使用dash.el图书馆,这就是您所需要的:
(-distinct (-non-nil '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
Run Code Online (Sandbox Code Playgroud)
dash.el由 Magnar Sveen 编写,它是一个很棒的列表操作库,具有适用于各种任务的许多功能。如果您编写大量 Elisp 代码,我建议安装它。函数-distinct删除列表中的重复元素,-non-nil删除nil元素。虽然上面的代码已经足够了,下面我描述了另一种方法,所以请随意忽略帖子的其余部分。
-non-nil在2.9版本中加入,因此,如果由于某种原因,你必须使用早期版本,另一种方式来达到同样的方法是使用-keep内置的identity功能,刚刚返回无论它被赋予:(identity 1) ; => 1。这个想法是-keep只保留谓词返回 true 的元素(Lisp 行话中的“非零”)。identity显然,仅针对非 nil 的任何值返回非 nil:
(-distinct (-keep 'identity '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
Run Code Online (Sandbox Code Playgroud)