elisp中多个列表的交集

pic*_*ick 5 lisp elisp

如何使用elisp获取多个列表的交集?我是一个elisp新手,但我想象有一些内置函数或使用reduce的更好的解决方案.我把它拼凑在一起,但看起来过于复杂.

;; get the intersection of these lists
;; result should be (3 4 5)
(setq test '((0 1 2 3 4 5) (2 3 4 5 6) (3 4 5 6 7)))

(require 'cl-lib)
(cl-remove-if-not
 (lambda (x) (cl-every
         (lambda (y) (> (length (memq x y) ) 0 ) )
         (cdr test) ) )
 (car test) )
;; ( 3 4 5)
Run Code Online (Sandbox Code Playgroud)

Ren*_*nzo 7

有一个cl-intersection只需要两个操作数:

(cl-intersection '(0 1 2 3 4 5) '(2 3 4 5 6))
Run Code Online (Sandbox Code Playgroud)

您可以使用它来定义您自己的交叉点:

(defun my-intersection(l)
    (cond ((null l) nil)
          ((null (cdr l)) (car l))
          (t (cl-intersection (car l) (my-intersection (cdr l))))))

(my-intersection '((0 1 2 3 4 5) (2 3 4 5 6) (3 4 5 6 7)))
Run Code Online (Sandbox Code Playgroud)

更新

感谢下面的@Tobias注释,你可以在新函数中使用相同的关键字参数cl-intersection,即(:test :test-not :key),并将它们传播到递归内的所有调用.

这是扩展版本:

(defun my-intersection(l &rest cl-keys)
    (cond ((null l) nil)
          ((null (cdr l)) (car l))
          (t (apply 'cl-intersection (car l) (apply 'my-intersection (cdr l) cl-keys) cl-keys))))
Run Code Online (Sandbox Code Playgroud)

  • 建议:添加一个参数`&rest rest`并将`cl-intersection`替换为`(apply'cl-intersection(car l)(应用'my-intersection(cdr l)rest)rest)`.通过这种方式,您可以使用像`:test`这样的可选参数.也许作为扩展版本. (2认同)