从lisp中的任何给定列表中,我想得到该列表元素的两个元素组合,而没有重复的组合(意思是(a b)=(b a),应该删除一个)
例如,如果我有一个列表(a b c d),
我想得到((a b)(a c)(a d)(b c)(b d)(c d))
答案 0 :(得分: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))
答案 1 :(得分: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)))
代替。我有理由相信loop
append
指令比同名函数更有效。
答案 2 :(得分: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,所以我希望这不是太难看。 : - )
答案 3 :(得分:1)
原则上,这类似于Rainer的Joswig答案,除了它不使用循环。
(defun combinations (list)
(mapcon (lambda (x) (mapcar (lambda (y) (list (car x) y)) (cdr x))) list))
让我对您的示例感到困惑的一件事是,(a a)
符合您对所需结果的口头描述,但在结果示例中,您已将其排除在外。
答案 4 :(得分: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))