TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: fools on December 04, 2017, 09:45:07 AM

Title: How to merge lists more effectively based on the same elements?
Post by: fools on December 04, 2017, 09:45:07 AM
Input list:
(setq lst1 '(("1D61" "1D62")
       ("1D61" "1D62")
       ("1D63" "1D64" "1DB6")
       ("1D63" "1D64" "1D65")
       ("1D64" "1D65" "1D66")
       ("1D65" "1D66" "1D67")
       ("1D66" "1D67" "1D68")
       ("1D67" "1D68" "1DBE")
       ("1D7F" "1D80")
       ("1D7F" "1D80")
       ("1D81" "1D82" "1D83")
       ("1D81" "1D82" "1D83" "1D85")
       ("1D81" "1D82" "1D83")
       ("1D84" "1D85" "1D86")
       ("1D82" "1D84" "1D85" "1D86")
       ("1D84" "1D85" "1D86")
       ("1D63" "1DB6" "1DBF")
       ("1D68" "1DBE")
       ("1DB6" "1DBF")
      )
)

Each of the sublists in the output list has different elements.
Output list:
(setq lst2 '(("1D61" "1D62")
        ("1D63" "1D64" "1D65" "1D66" "1D67" "1D68" "1DB6" "1DBE" "1DBF")
        ("1D7F" "1D80")
        ("1D81" "1D82" "1D83" "1D84" "1D85" "1D86")
       )
)

It's my way, but it's too tedious.I hope to improve the combined efficiency.
All suggestions and opinions are welcome. Thanks.
Code - Auto/Visual Lisp: [Select]
  1. (defun foo (lst / item more out same tmp)
  2.   (while lst
  3.     (setq item (car lst)
  4.           more t
  5.     )
  6.     (while more
  7.       (setq tmp nil)
  8.       (foreach id item
  9.         (if (setq same (vl-remove-if-not '(lambda (x) (member id x)) lst))
  10.           (setq lst  (vl-remove-if '(lambda (x) (member id x)) lst)            
  11.                 tmp (append (cons item same) tmp)
  12.           )
  13.         )
  14.       )
  15.       (if tmp
  16.         (setq item (merge (apply 'append tmp)))
  17.         (setq more nil)
  18.       )
  19.     )
  20.     (setq out (cons item out))
  21.   )
  22.   out
  23. )
  24.  
  25. (defun merge (lst / tmp)
  26.   (foreach item (acad_strlsort lst)
  27.     (if (not (and tmp (equal (car tmp) item)))
  28.       (setq tmp (cons item tmp))
  29.     )
  30.   )
  31.   (reverse tmp)
  32. )
Title: Re: How to merge lists more effectively based on the same elements?
Post by: Lee Mac on December 04, 2017, 02:09:29 PM
How about:
Code - Auto/Visual Lisp: [Select]
  1. (defun foo ( lst / rtn tmp )
  2.     (foreach itm lst
  3.         (if (vl-some '(lambda ( x ) (setq tmp (vl-some '(lambda ( y ) (if (member x y) y)) rtn))) itm)
  4.             (setq rtn (subst (append tmp (vl-remove-if '(lambda ( x ) (member x tmp)) itm)) tmp rtn))
  5.             (setq rtn (cons itm rtn))
  6.         )
  7.     )
  8.     (reverse rtn)
  9. )
Title: Re: How to merge lists more effectively based on the same elements?
Post by: fools on December 04, 2017, 08:53:21 PM
How about:

Lee, thank you very much. Whenever I meet a problem, I can always get your help.
When the amount of data is large, your program is so many times faster than mine.
Title: Re: How to merge lists more effectively based on the same elements?
Post by: fools on December 05, 2017, 09:29:46 AM
How about:
Code - Auto/Visual Lisp: [Select]
  1. (defun foo ( lst / rtn tmp )
  2.     (foreach itm lst
  3.         (if (vl-some '(lambda ( x ) (setq tmp (vl-some '(lambda ( y ) (if (member x y) y)) rtn))) itm)
  4.             (setq rtn (subst (append tmp (vl-remove-if '(lambda ( x ) (member x tmp)) itm)) tmp rtn))
  5.             (setq rtn (cons itm rtn))
  6.         )
  7.     )
  8.     (reverse rtn)
  9. )

A little bug.  :cry:
When two adjacent items are different and have some same items with the following, will return error result.
Like this:
(setq lst '(("1D22" "1DC7")   ("1D23" "1D24") ("1D24" "1DC7")))
(foo lst)  --> (("1D22" "1DC7") ("1D23" "1D24" "1DC7"))

The correct result is (("1D22" "1D23" "1D24" "1DC7"))
Title: Re: How to merge lists more effectively based on the same elements?
Post by: ribarm on December 05, 2017, 10:53:06 AM
How about :

Code - Auto/Visual Lisp: [Select]
  1. (defun foogather ( lst / foo rtn )
  2.  
  3.     (defun foo ( lst / rtn tmp )
  4.         (foreach itm lst
  5.             (if (vl-some '(lambda ( x ) (setq tmp (vl-some '(lambda ( y ) (if (member x y) y)) rtn))) itm)
  6.                 (setq rtn (subst (append tmp (vl-remove-if '(lambda ( x ) (member x tmp)) itm)) tmp rtn))
  7.                 (setq rtn (cons itm rtn))
  8.             )
  9.         )
  10.         (reverse rtn)
  11.     )
  12.  
  13.     (setq rtn (foo lst))
  14.     (while (not (equal rtn (setq rtn (foo rtn)))))
  15.     rtn
  16. )
  17.  

Quote
Untested though...
Title: Re: How to merge lists more effectively based on the same elements?
Post by: fools on December 06, 2017, 02:36:36 AM
How about :

Thanks for reply.
This is really a way, but perhaps also have some optimized space.