elisp 中多个列表的交集
Intersection of multiple lists in 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)
有一个只需要两个操作数的cl-intersection
:
(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))))
Install dash
third-party list manipulation library (follow instructions 安装)。那你需要:
(-reduce '-intersection '((1 2 3 4) (2 3 4 5) (3 4 5 6))) ; => (3 4)
如果您需要一个接受可变数量列表的函数,而不是单个列表列表,请使用 &rest
关键字将其包装在一个函数中,例如:
(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)
如果是第一次使用-reduce
, it's a “fold” function: it takes a binary function, a list of elements, and reduces them to a final result one list element at a time. This answer解释折叠背后的概念。
如何使用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-intersection
:
(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))))
Install dash
third-party list manipulation library (follow instructions 安装)。那你需要:
(-reduce '-intersection '((1 2 3 4) (2 3 4 5) (3 4 5 6))) ; => (3 4)
如果您需要一个接受可变数量列表的函数,而不是单个列表列表,请使用 &rest
关键字将其包装在一个函数中,例如:
(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)
如果是第一次使用-reduce
, it's a “fold” function: it takes a binary function, a list of elements, and reduces them to a final result one list element at a time. This answer解释折叠背后的概念。