Emacs 在elisp中剥离字符串列表中的重复元素
给出一个列表,例如Emacs 在elisp中剥离字符串列表中的重复元素,emacs,elisp,Emacs,Elisp,给出一个列表,例如 (list "foo" "bar" nil "moo" "bar" "moo" nil "affe") 我如何在删除重复字符串的情况下构建一个新列表,以及剥离nils,即 (list "foo" "bar" "moo" "affe") 需要保留元素的顺序-不能删除字符串的第一次出现 我在这里处理的列表很短,因此没有必要使用哈希表之类的东西来进行唯一性检查,尽管这样做肯定不会有什么坏处。但是,使用cl功能不是一个可行的选择。现在开始: (defun strip-duplic
(list "foo" "bar" nil "moo" "bar" "moo" nil "affe")
我如何在删除重复字符串的情况下构建一个新列表,以及剥离nil
s,即
(list "foo" "bar" "moo" "affe")
需要保留元素的顺序-不能删除字符串的第一次出现
我在这里处理的列表很短,因此没有必要使用哈希表之类的东西来进行唯一性检查,尽管这样做肯定不会有什么坏处。但是,使用cl
功能不是一个可行的选择。现在开始:
(defun strip-duplicates (list)
(let ((new-list nil))
(while list
(when (and (car list) (not (member (car list) new-list)))
(setq new-list (cons (car list) new-list)))
(setq list (cdr list)))
(nreverse new-list)))
特别是,包含许多列表操作函数
是的,我知道你说过你不想使用
cl
。但我仍然认为这是一种正确的方法,可以帮助其他可能阅读本文的人
(为什么cl
对您来说不可行?它与Emacs一起发布已经有大约20年了,不算过去版本中功能较少的版本。)尝试以下方法:
如果您使用library,您只需要:
(-distinct (-non-nil '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
dash.el
是由Magnar Sveen编写的,它是一个伟大的列表操作库,具有许多用于各种任务的函数。如果您编写了大量的Elisp代码,我建议您安装它。函数删除列表中的重复元素,删除nil
元素。虽然上面的代码已经足够了,但下面我描述了一种替代方法,所以可以忽略本文的其余部分
-版本2.9中添加了非nil
,因此如果出于某种原因必须使用早期版本,另一种方法是使用内置函数,该函数只返回给定的值:(标识1);=>1
。其思想是-keep
只保留谓词返回true的元素(Lisp术语中的“non-nil”)identity
显然只对非零的值返回非零:
(-distinct (-keep 'identity '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
这是一个简短的例子:
(delete-duplicates '("~/.emacs.d" "~/.emacs.d") :test #'string-equal) ;; '("~/emacs.d")
基本上,您可以使用:test
关键字来选择函数string equal
,以测试元素是否重复
否则默认函数测试不会检查字符串是否相等。这很好地解决了这个问题。我现在已经了解了
会员
。还有一个类似的函数允许指定比较函数吗?不,我不知道。不过,编写起来会非常简单。还有memq
和memql
。在重新创建已有实现的通用模式(在本例中为delete dup
)之前,先阅读文档.如果你好奇的话,你可以比较一下你的实现:我一直在为Gnus做一些小补丁,在它的提交日志中,我经常看到一些变化,用一个非cl等价物替换cl中的某些东西。我不太清楚确切的原因是什么,但很可能是因为支持奇怪的Emacs风格或版本,或者除非真的有必要,否则尽量避免加载cl
包。@rafl我相信对cl
的限制是从RMS保持Emacs lisp小型化的愿望开始的。看看最近讨论这一点的帖子:@Trey:哦,我明白了。为了使Emacs的核心保持小型,需要每个包重新实现它们自己的基本数据结构和功能。好吧,如果你决定Emacs的核心将完全包含你所使用的特性,那么它是有效的。其他人都得到了重复的努力和膨胀…更加优雅和直接。有时我真的希望有类似于名称空间的东西将相关函数分组在一起,或者可能有一个更一致的命名方案,允许通过猜测它的名称来查找特定的东西:-/分组(通过命名约定或名称空间)很难,因为分组的方法总是很多。Emacs并不努力做到这一点,而是提供了类似于apropos
的功能。但这也不理想。我们可能应该更加努力,尽管现在纠正大多数违法者有点晚了。
(-distinct (-keep 'identity '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
(delete-duplicates '("~/.emacs.d" "~/.emacs.d") :test #'string-equal) ;; '("~/emacs.d")