如何在emacs lisp中计算两个集合之间的差异,集合应该是列表

如何在emacs lisp中计算两个集合之间的差异,集合应该是列表,lisp,elisp,set,set-difference,Lisp,Elisp,Set,Set Difference,如何在Emacs Lisp中计算两个集合之间的差异?集合应该是列表。 程序应该非常简单和简短,否则我就不懂了。我是新手 Thx在通用Lisp扩展中有一个设置差异函数: elisp> (require 'cl-lib) cl-lib elisp> (cl-set-difference '(1 2 3) '(2 3 4)) (1) 免责声明:这不是在eLisp中执行此操作的有效方法。一种有效的方法是通过一个带有哈希函数的哈希表,但既然您询问了列表,那么它就是: (defun custo

如何在Emacs Lisp中计算两个集合之间的差异?集合应该是列表。 程序应该非常简单和简短,否则我就不懂了。我是新手


Thx

在通用Lisp扩展中有一个
设置差异
函数:

elisp> (require 'cl-lib)
cl-lib
elisp> (cl-set-difference '(1 2 3) '(2 3 4))
(1)

免责声明:这不是在eLisp中执行此操作的有效方法。一种有效的方法是通过一个带有哈希函数的哈希表,但既然您询问了列表,那么它就是:

(defun custom-set-difference (a b)
  (remove-if
     #'(lambda (x) (and (member x a) (member x b)))
     (append a b)))

(custom-set-difference '(1 2 3 4 5) '(2 4 6))

(1 3 5 6)

(defun another-set-difference (a b)
  (if (null a) b
    (let (removed)
      (labels ((find-and-remove
                (c)
                (cond
                 ((null c) nil)
                 ((equal (car c) (car a))
                  (setq removed t) (cdr c))
                 (t (cons (car c) (find-and-remove (cdr c)))))))
        (setf b (find-and-remove b))
        (if removed
            (another-set-difference (cdr a) b)
          (cons (car a) (another-set-difference (cdr a) b)))))))

(another-set-difference '(1 2 3 4 5) '(2 4 6))

(1 3 5 6)
第二种方法的效率稍高一些,因为它在进行后续检查时会删除元素,但第一种方法更短,更直接


还要注意,列表不是集合的良好表示,因为它们自然允许重复。哈希映射更适合于此目的。

这里有一个简单而简短的定义,应该很容易理解。它本质上与Emacs的公共Lisp库中的
set difference
函数相同,但没有对测试参数进行任何处理

(defun set-diff (list1 list2 &optional key)
  "Combine LIST1 and LIST2 using a set-difference operation.
Optional arg KEY is a function used to extract the part of each list
item to compare.

The result list contains all items that appear in LIST1 but not LIST2.
This is non-destructive; it makes a copy of the data if necessary, to
avoid corrupting the original LIST1 and LIST2."
  (if (or (null list1)  (null list2))
      list1
    (let ((keyed-list2  (and key  (mapcar key list2)))
          (result       ()))
      (while list1
        (unless (if key
                    (member (funcall key (car list1)) keyed-list2)
                  (member (car list1) list2))
          (setq result  (cons (car list1) result)))
        (setq list1  (cdr list1)))
      result)))

当我编写包含大量列表数据转换的Elisp代码时,我使用库,因为它有大量函数用于处理列表。设置差异可通过以下方式完成:


GNU Emacs Lisp参考手册,建议使用cl库
cl设置差异LIST1 LIST2
&key:test:test not:key

(require 'cl-lib)
(cl-set-difference '(1 2 3) '(2 3 4))
(1)

您可能也在寻找两个集合的并集和交集的差异:
(let((a'(1 2 3 4))(b'(3 4 5 6))(-difference(-union a b)(-intersection a b));;=>'(1 2 5 6)
现在,需要'cl lib而不是不推荐的'cl,并将函数命名为
cl set difference
@TommyJollyboat:谢谢-我已经更新了答案。
(require 'cl-lib)
(cl-set-difference '(1 2 3) '(2 3 4))
(1)