Alexandria有一个函数map-product
,它接å—​​任æ„æ•°é‡çš„列表å‚数,并按顺åºç”Ÿæˆå…ƒç´ 的所有组åˆï¼Œæ¯ä¸ªå…ƒç´ 组åˆä¸€ä¸ªã€‚例如:
(alexandria:map-product 'list '(1 2) '(3 4) '(5 6))
=> ((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
当å‚æ•°ä¸å˜åœ¨é‡å¤å…ƒç´ 时,结果组åˆä¹Ÿå°†åŒ…å«ä¸€äº›é‡å¤å…ƒç´ :
(alexandria:map-product 'list '(1 2) '(3 4) '(5 1))
=> ((1 3 5) (1 3 1) (1 4 5) (1 4 1) (2 3 5) (2 3 1) (2 4 5) (2 4 1))
å…¶ä¸ï¼ˆ1 3 1)和(1 4 1)包å«é‡å¤é¡¹ã€‚
我想从结果ä¸åˆ 除包å«é‡å¤é¡¹çš„所有æ¤ç±»åˆ—表。我目å‰çš„解决方案是简å•åœ°åšï¼š
(delete-if-not #'alexandria:setp result)
但这需è¦è¿‡å¤šçš„åŽå¤„ç†ï¼Œç‰¹åˆ«æ˜¯å› 为产生的组åˆæ•°é‡é€šå¸¸ä¸ºæ•°ç™¾ä¸ªã€‚一个更好的解决方案是编写åƒmap-product
è¿™æ ·çš„å‡½æ•°ï¼Œå®ƒé¦–å…ˆä¸ä¼šç”Ÿæˆé‡å¤é¡¹ã€‚
zck在Lisp: How to get all possible combinations of the elements from lists contained on a list?çš„å¦ä¸€ç¯‡æ–‡ç« æ供的函数大致相当于map-product
,似乎å¯ä»¥ä¿®æ”¹å®ƒä»¥åœ¨å†…éƒ¨åˆ é™¤é‡å¤é¡¹ï¼š
(defun combinations (&rest lists)
(if (car lists)
(mapcan (lambda (inner-val)
(mapcar (lambda (outer-val)
(cons outer-val
inner-val))
(car lists)))
(apply #'combinations (cdr lists)))
(list nil)))
然而,对我æ¥è¯´ï¼Œå¦‚何æ’å…¥é‡å¤æµ‹è¯•å¹¶ä¸æ˜Žæ˜¾ã€‚æ¤å¤–,一个简å•çš„计时è¿è¡Œä¼¼ä¹Žè¡¨æ˜Žè¿™ä¸ªå‡½æ•°æ¯”alexandria:map-product
慢大约16å€ã€‚获得æ¤åŠŸèƒ½çš„更快版本是å¦å¯è¡Œï¼Œä½†æ²¡æœ‰é‡å¤ç»„åˆï¼Ÿ
ç”案 0 :(得分:1)
ä½ å¯èƒ½éœ€è¦æ£€æŸ¥ä¸€ä¸‹è¿™æ˜¯å¦æ£ç¡®ï¼Œä½†å®ƒåº”è¯¥ç»™ä½ ä¸€ä¸ªæƒ³æ³•ï¼š
CL-USER 40 > (defun combinations-1 (lists)
(if (car lists)
(mapcan (lambda (inner-val)
(mapcan (lambda (outer-val)
(unless (member outer-val inner-val)
(list (cons outer-val inner-val))))
(car lists)))
(combinations-1 (cdr lists)))
(list nil)))
COMBINATIONS-1
CL-USER 41 > (combinations-1 '((3 2) (1 2) (5 1)))
((3 1 5) (2 1 5) (3 2 5) (3 2 1))
å¦ä¸€ä¸ªMAPCAN而ä¸æ˜¯MAPCAR过滤NIL。为æ¤ï¼Œæˆ‘们需è¦è¿”å›žåˆ—è¡¨ï¼Œå› æ¤æ·»åŠ 了LIST调用。我们åªåœ¨åˆ—表ä¸æ·»åŠ 内容,如果它ä¸æ˜¯æˆå‘˜ï¼Œå¦åˆ™ä½¿ç”¨ç©ºåˆ—表。
请注æ„ï¼Œæˆ‘è¿˜åˆ é™¤äº†ï¼†amp; rest list / apply pattern。
问:所有é‡å¤çš„å列表是å¦éƒ½å‡å°‘到NIL,以便通过MAPCANåˆ é™¤å®ƒä»¬ï¼Ÿ