1

从lisp中的任何给定列表中,我想获得该列表元素的两个元素组合,而没有重复的组合(意思是(ab)=(ba),应该删除一个)

因此,例如,如果我有一个 (abcd) 列表,

我想得到 ((ab) (ac) (ad) (bc) (bd) (cd))

4

5 回答 5

5
(defun combinations (list)
  (loop for (a1 . r1) on list
        nconc (loop for a2 in r1 collect (list a1 a2))))


CL-USER 172 > (combinations '(a b c d))
((A B) (A C) (A D) (B C) (B D) (C D))
于 2013-02-07T21:52:34.127 回答
2

假设我正确理解你,我会使用mapcar和朋友。

(defun pair-with (elem lst)
  (mapcar (lambda (a) (list elem a)) lst))

(defun unique-pairs (lst)
  (mapcon (lambda (rest) (pair-with (car rest) (cdr rest)))
          (remove-duplicates lst)))

那应该让你

CL-USER> (unique-pairs (list 1 2 3 4 5))
((1 2) (1 3) (1 4) (1 5) (2 3) (2 4) (2 5) (3 4) (3 5) (4 5))
CL-USER> (unique-pairs (list :a :b :c :a :b :d))
((:C :A) (:C :B) (:C :D) (:A :B) (:A :D) (:B :D))

如果你不害怕loop,你也可以把第二个写得稍微清楚一点

(defun unique-pairs (lst)
  (loop for (a . rest) on (remove-duplicates lst)
        append (pair-with a rest)))

反而。我有理由确定loopsappend指令比同名函数更有效。

于 2013-02-07T21:36:03.503 回答
1

原则上,这类似于 Rainer 的 Joswig 答案,只是它不使用循环。

(defun combinations (list)
  (mapcon (lambda (x) (mapcar (lambda (y) (list (car x) y)) (cdr x))) list))

让我对您的示例感到困惑的一件事是(a a)与您对所需结果的口头描述相匹配,但在结果示例中您已将其排除在外。

于 2013-02-08T16:20:16.377 回答
1

方案解决:

(define (lol lst)
  (let outer ((lhs lst))
    (if (null? lhs)
        '()
        (let inner ((rhs (cdr lhs)))
          (if (null? rhs)
              (outer (cdr lhs))
              (cons (list (car lhs) (car rhs)) (inner (cdr rhs))))))))

以及相同的 Common Lisp 翻译:

(defun lol (list)
  (labels ((outer (lhs)
             (and lhs (labels ((inner (rhs)
                                 (if rhs
                                     (cons (list (car lhs) (car rhs))
                                           (inner (cdr rhs)))
                                     (outer (cdr lhs)))))
                        (inner (cdr lhs))))))
    (outer list)))

抱歉,我不是 Common Lisper,所以我希望这不会太难看。:-)

于 2013-02-07T18:39:53.353 回答
0

这是我自己的初步回答。它可能不是完全有效,但它解决了问题。

(remove nil (let ((res))
             (dotimes (n (length test-list) res)
                (setq res
                     (append res
                        (let ((res2) (rest-list (remove (nth n test-list) test-list)))
                         (dotimes (m (length rest-list) res2)
                            (setq res2
                                 (append res2
                                   (list (if (< (nth n test-list) (nth m rest-list))
                                         (list (nth n test-list) (nth m rest-list))
                                          nil)))))))))))

如果删除第 9 行的“if 语句”,则结果也将包含重复项,结果将是

((a b) (a c) (a d) (a a) (b a) (b c) (b d) (b b) 
 (c a) (c b) (c d) (c c) (d a) (d b) (d c) (d d))
于 2013-02-07T19:03:14.793 回答