Lisp实现:从任意数量列表生成所有元素组合
生成任意数量列表的元素组合
你现有的二元组合函数返回的是点对结构,要推广到任意数量列表且保持清晰的列表格式,可以调整思路,先把二元组合的输出改成列表结构,再通过递归处理多列表的笛卡尔积。
先改进二元组合函数,让它返回列表的列表(而非点对),逻辑更直观:
(defun comb2 (x y) (loop for a in x nconc (loop for b in y collect (list a b))))
调用(comb2 '(1 2) '(a b))会返回((1 a) (1 b) (2 a) (2 b)),结构更规整。
接下来实现支持任意数量列表的组合函数,通过递归处理:
(defun combine (&rest lists) (cond ((null lists) nil) ((null (cdr lists)) (mapcar #'list (car lists))) (t (loop for elem in (car lists) nconc (loop for combo in (apply #'combine (cdr lists)) collect (cons elem combo))))))
这个函数的逻辑是:
- 如果没有传入列表,返回空
- 如果只有一个列表,把每个元素单独包装成列表
- 如果有多个列表,取第一个列表的每个元素,拼接到剩余列表所有组合的前面,最终生成所有可能的笛卡尔积
示例调用:
(combine '(1 2) '(a b) '(x y))
返回结果:
((1 a x) (1 a y) (1 b x) (1 b y) (2 a x) (2 a y) (2 b x) (2 b y))
这样的输出是标准的列表嵌套结构,不会出现嵌套点对的格式问题。如果需要和原函数一样的逆序结果,可以在最后对结果做reverse处理,或者调整循环的遍历顺序。
内容的提问来源于stack exchange,提问作者Mattias Smedstad
相关产品推荐
相关产品推荐

