检查子列表中带有值的关键字的出现

时间:2018-07-17 02:07:54

标签: lisp common-lisp plist

我有一个数据结构,由列表内的属性列表组成,列表本身位于列表内。本质上是二维的矩阵。格式为:

(((:VALUE 0 :GROUP 0) (:VALUE 0 :GROUP 0))
 ((:VALUE 0 :GROUP 0) (:VALUE 0 :GROUP 0))
 ((:VALUE 0 :GROUP 0) (:VALUE 0 :GROUP 0)))

每个:value和:group将包含一个任意整数值。我需要确定:group关键字是否为0。我一直在尝试使用member函数来实现这一点,但是它只会返回nil

假设数据结构称为data,我的代码是:

(member '(:group 0) data :test 'equal))

如何使用member函数检查子列表的子列表中:group 0的出现? (如果确实可行,或者我应该使用几个循环进行迭代?)

1 个答案:

答案 0 :(得分:6)

尝试getf:keyfind/find-if 和/或remove/remove-if-not

1级嵌套

准备数据

(defparameter *data-1*
  (loop repeat 10 collect (list :value (random 10) :group (random 10))))
*data-1*
((:VALUE 7 :GROUP 4) (:VALUE 9 :GROUP 6) (:VALUE 2 :GROUP 7) (:VALUE 8 :GROUP 2)
 (:VALUE 5 :GROUP 6) (:VALUE 4 :GROUP 7) (:VALUE 3 :GROUP 5) (:VALUE 8 :GROUP 7)
 (:VALUE 0 :GROUP 3) (:VALUE 5 :GROUP 5))

A:找到第7组的第一个事件:

(find 7 *data-1* :key (lambda (pl) (getf pl :group)))
==> (:VALUE 2 :GROUP 7)

B:查找第7组的所有事件:

(remove 7 *data-1* :key (lambda (pl) (getf pl :group)) :test-not #'eql)
==> ((:VALUE 2 :GROUP 7) (:VALUE 4 :GROUP 7) (:VALUE 8 :GROUP 7))

2级嵌套

准备数据:

(defparameter *data-2*
  (loop repeat 10 collect
      (loop repeat (random 4) collect
          (list :value (random 10) :group (random 10)))))
*data-2*
(((:VALUE 9 :GROUP 9) (:VALUE 8 :GROUP 2) (:VALUE 6 :GROUP 7)) NIL
 ((:VALUE 9 :GROUP 5)) ((:VALUE 9 :GROUP 1)) NIL
 ((:VALUE 2 :GROUP 7) (:VALUE 6 :GROUP 5) (:VALUE 2 :GROUP 1))
 ((:VALUE 1 :GROUP 4) (:VALUE 5 :GROUP 5))
 ((:VALUE 9 :GROUP 7) (:VALUE 9 :GROUP 8) (:VALUE 7 :GROUP 4))
 ((:VALUE 4 :GROUP 7)) NIL)

C:找到第7组的第一事件:

(find-if (lambda (l)
           (find 7 l :key (lambda (pl) (getf pl :group))))
         *data-2*)
==> ((:VALUE 9 :GROUP 9) (:VALUE 8 :GROUP 2) (:VALUE 6 :GROUP 7))

D:查找第7组的所有事件:

(remove-if-not (lambda (l)
                 (find 7 l :key (lambda (pl) (getf pl :group))))
               *data-2*)
==>
(((:VALUE 9 :GROUP 9) (:VALUE 8 :GROUP 2) (:VALUE 6 :GROUP 7))
 ((:VALUE 2 :GROUP 7) (:VALUE 6 :GROUP 5) (:VALUE 2 :GROUP 1))
 ((:VALUE 9 :GROUP 7) (:VALUE 9 :GROUP 8) (:VALUE 7 :GROUP 4))
 ((:VALUE 4 :GROUP 7)))

定义功能:

根据您的需求,您可能需要定义功能

(defun get-group (plist)
  (getf plist :group))
(defun find-group (list-of-plists group)
  (find group list-of-plists :key #'get-group))
(defun make-group-finder (group)
  (lambda (list-of-plists) (find-group list-of-plists group)))

现在您可以将它们用于上述任务:

A: (find-group *data-1* 7)

B: (remove 7 *data-1* :key #'get-group :test-not #'eql)

C: (find-if (make-group-finder 7) *data-2*)

D: (remove-if-not (make-group-finder 7) *data-2*)

PS remove-if-not是“过滤器”的Lisp惯用语。