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

时间:2010-09-28 17:32:12

标签: emacs elisp

给出一个列表,如

(list "foo" "bar" nil "moo" "bar" "moo" nil "affe")

我如何建立一个删除了重复字符串的新列表,以及nil被剥离的字符串,即

(list "foo" "bar" "moo" "affe")

需要保留元素的顺序 - 可能无法删除字符串的第一个出现。

我在这里处理的列表很短,所以没有必要使用哈希表之类的东西来进行唯一性检查,尽管这样做肯定也不会受到影响。但是,使用cl功能不是一个可行的选择。

5 个答案:

答案 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个元素。虽然上面的代码已经足够了,但我在下面描述了另一种方法,所以请随意忽略帖子的其余部分。

在版本2.9中添加了

-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 来测试元素是否重复。

否则默认函数测试不会检查字符串是否相等。