如何计算Emacs Lisp中两组之间的差异?这些集应该是列表。 该程序应该非常简单和简短,否则我将无法理解它。我是个新人。
THX
答案 0 :(得分:8)
Common Lisp扩展中有一个set-difference
函数:
elisp> (require 'cl)
cl
elisp> (set-difference '(1 2 3) '(2 3 4))
(1)
答案 1 :(得分:2)
免责声明:这不是在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)
第二个稍微提高效率,因为它会在进行后续检查时删除元素,但第一个更短更直接。
另请注意,列表不是集合的良好表示,因为它们自然允许重复。哈希地图更适合这个目的。
答案 2 :(得分:2)
这是一个简单的&简短的定义,应该很容易理解。它与Emacs的Common Lisp库中的set-difference
函数基本相同,但没有任何TEST参数的处理。
(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)))
答案 3 :(得分:2)
当我编写包含大量列表数据转换的Elisp代码时,我使用dash
库,因为它有大量函数可以处理列表。可以使用-difference
:
(-difference '(1 2 3 4) '(3 4 5 6)) ;; => '(1 2)
答案 4 :(得分:0)
GNU Emacs Lisp参考手册,Sets and Lists建议使用 cl-lib 的
cl设置差异 LIST1 LIST2 &key :test :test-not :key
(require 'cl-lib)
(cl-set-difference '(1 2 3) '(2 3 4))
(1)