生成组合

时间:2018-01-28 18:20:48

标签: list loops lisp common-lisp combinations

我正在尝试在Lisp中编写一个函数,它生成给定键和值的所有可能组合。以下是输入和输出示例:

#dealss .slick-slider {
font-size: 30px;
line-height: 1;
text-align: center;
color: white;

目前,我执行此操作的功能如下:

.slick-slide {
background: rgba(255,255,255,.4);
padding: 40px 0;

对于上面给出的输入,函数按预期工作:

}
  

但是,对于更长的输入,输出不再正确!

Input: '((key1 . (v1 v2))
         (key2 . (v3 v4)))

Output: '(((key1 . v1)(key2 . v3))
          ((key1 . v1)(key2 . v4))
          ((key1 . v2)(key2 . v3))
          ((key1 . v2)(key2 . v4)))

请注意,在上面的输出中,(defun generate-selectors (selectors) (cond ((= (length selectors) 0) nil) ((= (length selectors) 1) (let* ((keys (mapcar #'first selectors)) (key (first keys)) (values (rest (assoc key selectors)))) (loop for val in values collect (cons key val)))) (t (let* ((keys (mapcar #'first selectors)) (key (first keys)) (values (rest (assoc key selectors))) (rest (remove (assoc key selectors) selectors))) (loop for r in (generate-selectors rest) append (loop for val in values collect (cons (cons key val) (list r)))))))) > (generate-selectors '((key1 . (v1 v2 v3)) (key2 . (v4 v5)))) (((KEY1 . V1) (KEY2 . V4)) ((KEY1 . V2) (KEY2 . V4)) ((KEY1 . V3) (KEY2 . V4)) ((KEY1 . V1) (KEY2 . V5)) ((KEY1 . V2) (KEY2 . V5)) ((KEY1 . V3) (KEY2 . V5))) 嵌套在另一个子列表中。正确的输出应如下所示:

> (generate-selectors '((key1 . (v1 v2 v3)) (key2 . (v4 v5)) (key3 . (v6))))
  (((KEY1 . V1) ((KEY2 . V4) (KEY3 . V6)))
   ((KEY1 . V2) ((KEY2 . V4) (KEY3 . V6)))
   ((KEY1 . V3) ((KEY2 . V4) (KEY3 . V6)))
   ((KEY1 . V1) ((KEY2 . V5) (KEY3 . V6)))
   ((KEY1 . V2) ((KEY2 . V5) (KEY3 . V6)))
   ((KEY1 . V3) ((KEY2 . V5) (KEY3 . V6))))

我的KEY2函数导致了什么?

编辑:如果未在列表中包装KEY3,我会收到以下输出:

(((KEY1 . V1) (KEY2 . V4) (KEY3 . V6))
 ((KEY1 . V2) (KEY2 . V4) (KEY3 . V6))
 ...                                  )

2 个答案:

答案 0 :(得分:5)

鉴于以前的解决方案是正确的,我想提出一个替代解决方案。给定列表A1,A2,... An,以下函数执行它们的笛卡尔积(A1 x A2 x ... x An):

(defun cartesian-product (l)
  (if (null l)
      (list nil)
      (loop for x in (car l) 
            nconc (loop for y in (cartesian-product (cdr l)) collect (cons x y)))))

然后函数generate-selectors可以定义为:

(defun generate-selectors (selectors)
  (cartesian-product (loop for s in selectors
                       collect (loop for val in (cdr s) collect (cons (car s) val)))))

答案 1 :(得分:2)

下面:

(cons (cons key val) (list r))

R是递归获得的,是列表。您将其包装在列表中。请尝试改为:

(cons (cons key val) r)

此外,当您在一般情况下致电append时,您需要列表。但是,您的基本情况不会生成列表列表,只会生成列表。 您需要在list

附近的基础案例中添加额外的cons
(loop for val in values
      collect (list (cons key val)))

另一个版本

如果你不需要钥匙,这个更简单一些。我按照Renzo的回答命名函数product,因为你所做的是Cartesian product

(defun product (lists)
  (if lists
      (destructuring-bind (head . lists) lists
        (loop
          with product = (product lists) 
          for value in head
          append (loop
                   for tuple in product
                   collect (cons value tuple))))
      (list (list))))

(product '((a b) (0 1 2)))
=> ((A 0) (A 1) (A 2) (B 0) (B 1) (B 2))