elisp中多个列表的交集

elisp中多个列表的交集,lisp,elisp,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-

如何使用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)

有一个只需要两个操作数的
cl交集

(cl-intersection '(0 1 2 3 4 5) '(2 3 4 5 6))
您可以使用它来定义自己的交叉点:

(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)))
已更新

由于下面的@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))))
安装第三方列表操作库(请按照以下步骤进行安装)。那么你需要:

(-reduce '-intersection '((1 2 3 4) (2 3 4 5) (3 4 5 6))) ; => (3 4)
如果您需要一个接受可变数量列表的函数,而不是单个列表,请使用关键字将其包装到函数中,如下所示:

(defun -intersection* (&rest list-of-lists)
  (-reduce '-intersection list-of-lists))
;; (-intersection* '(1 2 3 4) '(2 3 4 5) '(3 4 5 6)) ; => (3 4)

如果这是您第一次使用,它是一个“折叠”函数:它接受一个二进制函数,一个元素列表,并将它们减少到最终结果,一次一个列表元素。解释折叠背后的概念。

建议:添加一个参数
&rest-rest
,并用
替换
cl交叉口
(应用“cl交叉口(左车)(应用”我的交叉口(cdr-l)rest)
。通过这种方式,您可以使用可选参数,如
:test
等。也许是一个扩展版本。如果我想做同样的事情,除了向量呢?