没有é‡å¤å…ƒç´ çš„列表元素的所有组åˆ

时间:2017-06-07 01:59:05

标签: mapping common-lisp combinations

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å€ã€‚获得此功能的更快版本是å¦å¯è¡Œï¼Œä½†æ²¡æœ‰é‡å¤ç»„åˆï¼Ÿ

1 个答案:

答案 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调用。我们åªåœ¨åˆ—表中添加内容,如果它ä¸æ˜¯æˆå‘˜ï¼Œå¦åˆ™ä½¿ç”¨ç©ºåˆ—表。

请注æ„,我还删除了& rest list / apply pattern。

问:所有é‡å¤çš„å­åˆ—表是å¦éƒ½å‡å°‘到NIL,以便通过MAPCAN删除它们?