给出一个列表,如
(list "foo" "bar" nil "moo" "bar" "moo" nil "affe")
我如何建立一个删除了重复字符串的新列表,以及nil
被剥离的字符串,即
(list "foo" "bar" "moo" "affe")
需要保留元素的顺序 - 可能无法删除字符串的第一个出现。
我在这里处理的列表很短,所以没有必要使用哈希表之类的东西来进行唯一性检查,尽管这样做肯定也不会受到影响。但是,使用cl
功能不是一个可行的选择。
答案 0 :(得分:35)
在"Sets and Lists"的"Lists" section中尝试Emacs Lisp Reference Manual:
(delq nil (delete-dups (list "foo" "bar" nil "moo" "bar" "moo" nil "affe")))
答案 1 :(得分:16)
Common Lisp package包含许多列表操作函数,尤其是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)
是的,我意识到你说你不想使用cl
。但我仍然提到这是为其他可能阅读此帖的人做的正确方法。
(为什么cl
对你来说不可行?它已经与Emacs一起发售了大约20年,不计算过去的化身特征。)
答案 2 :(得分:4)
如果您使用dash.el
库,那就是您所需要的:
(-distinct (-non-nil '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
dash.el
由Magnar Sveen编写,它是一个很棒的列表操作库,具有许多用于各种任务的函数。如果你写了很多Elisp代码,我建议安装它。函数-distinct
删除列表中的重复元素,-non-nil
删除nil
个元素。虽然上面的代码已经足够了,但我在下面描述了另一种方法,所以请随意忽略帖子的其余部分。
-non-nil
,因此如果由于某种原因您必须使用早期版本,另一种实现相同目的的方法是使用内置-keep
函数的identity
,只返回给出的任何内容:(identity 1) ; => 1
。这个想法是-keep
只保留谓词返回true的元素(Lisp术语中的“非零”)。 identity
显然只返回非nil的非零值:
(-distinct (-keep 'identity '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
答案 3 :(得分:1)
这里你去:
(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)))
答案 4 :(得分:1)
这是一个简短的例子:
(delete-duplicates '("~/.emacs.d" "~/.emacs.d") :test #'string-equal) ;; '("~/emacs.d")
基本上,您使用 :test
关键字来选择函数 string-equal
来测试元素是否重复。
否则默认函数测试不会检查字符串是否相等。