在elisp中删除字符串列表中的重复元素

raf*_*afl 19 emacs elisp

给出一个列表如

(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)

  • 更加优雅和直接。Somtimes我真的希望有类似命名空间将相关功能分组在一起的东西,或者是一种更一致的命名方案,它允许通过猜测其名称来特别寻找某些东西:-/ (2认同)

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年,不计算过去的化身特征.)

  • @Trey:哦,我明白了.为了保持Emacs的核心小,需要每个包重新实现自己的基本数据结构功能.好吧,如果你是那个决定Emacs的核心将包含你所使用的功能的人,它就可以了.其他人都得到了重复的努力和膨胀...... (8认同)
  • @rafl我相信对`cl`的限制始于RMS'保持emacs-lisp小的愿望.查看最近讨论这一点的主题:http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01278.html (3认同)

Mir*_*lov 5

如果您使用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)