Compare items from two lists

Compare items from two lists

Anonymous
Not applicable
1,338 Views
13 Replies
Message 1 of 14

Compare items from two lists

Anonymous
Not applicable

I have two lists the main and any other list. How to buy the items in a way that if you only have the items from my main list in the other list, return T if not nil.
'(1 3 4 30) ;; main list

 

(:member '(1 3 4 30)' ( 1 3))
$ T
(:member '(1 3 4 30)' (1 5 6 7))
$ nil
(:member '(1 3 4 30)' (1 4 30))
$ T
[...]

 

 

(defun :member ( main lst )
  (vl-every '(lambda ( x ) (equal x main)) lst)
)

 

 

I'm going this way, but there should be an easy way to do this without needing a lot of if or cond?

0 Likes
Accepted solutions (2)
1,339 Views
13 Replies
Replies (13)
Message 2 of 14

doaiena
Collaborator
Collaborator
Accepted solution
(vl-every '(lambda ( x ) (vl-position x main)) lst)
Message 3 of 14

Anonymous
Not applicable

@doaiena That's right !!
Perfect and sorry to bother !!!

0 Likes
Message 4 of 14

CodeDing
Advisor
Advisor

@Anonymous ,

 

I'm sure that Visual LISP is faster, so doaiena's approach is probably best, but here is the AutoLISP equivalent:

(defun :member (main lst / )
  (apply 'and (mapcar '(lambda (x) (member x main)) lst))
);defun

Best,

~DD

Message 5 of 14

Anonymous
Not applicable

One more doubt!
and to compare if there is a maximum of 2 items in the main list as in the examples.

 

 

 

'(4 2 2 4 ) '(2 3)
$ T ;-> Two item of one type is T

'(4 2 2 4 ) '(4 3)
$ T ;-> Two item of one type is T

'(4 2 2 2 5) '(4 5 6 7)
$ T ;-> one of each tbm is T

'(4 2 2 2 4) '(4 5 6 7)
$ T ;-> one of each tbm is T

'(4 4 2 2 2 4) '(4 5 6 7)
$  nil ;-> More than two items NIL

'(4 2 2 2 4) '(2 5 6 7)
$  nil ;-> two types but not in the definition list NIL

'(4 2 2 4 3 ) '(4 3)
$ NIL 

 

 

 

 

 

0 Likes
Message 6 of 14

CodeDing
Advisor
Advisor

@Anonymous ,

 

I don't understand your new criteria..

Can you break it down into a bunch of if / then statements? That would help me visualize it better

0 Likes
Message 7 of 14

doaiena
Collaborator
Collaborator
Accepted solution

I think i've got the idea. Is this the result you are looking for @Anonymous ?

(defun test ( lst main / ctr item)

(setq ctr 0)
(while (and lst (< ctr 3))
(setq item (car lst) lst (cdr lst))
(if (vl-position item main) (setq ctr (1+ ctr)))
);while

(if (vl-position ctr (list 1 2)) T nil)
);defun
Message 8 of 14

Anonymous
Not applicable

I am not able to handle this algorithm well.
like this:
If you have a maximum of two items on my main list, return T

 
'(4 2 2 4 ) '(2 3)

note that I have two 2 on my main list and 2 is present on the secondary (that would be valid! T)

 

'(4 2 2 4 ) '(4 3)
note that I have two 4 on my main list and 2 is present on the secondary (that would be valid! T)
 
'(4 2 2 2 5) '(4 5 6 7)
If I have one of each on my main list (that would be valid! T)
 
'(4 4 2 2 2 4) '(4 5 6 7)
If I have more than two items I would return NIL
 
'(4 2 2 4 3 ) '(4 3)
if there are more than two I would return NIL
 
[...]

 

Message 9 of 14

Anonymous
Not applicable

@doaiena wrote:

I think i've got the idea. Is this the result you are looking for @Anonymous ?

(defun test ( lst main / ctr item)

(setq ctr 0)
(while (and lst (< ctr 3))
(setq item (car lst) lst (cdr lst))
(if (vl-position item main) (setq ctr (1+ ctr)))
);while

(if (vl-position ctr (list 1 2)) T nil)
);defun

 

Wow !!! where do you learn ??
Exactly!!! Thank you one more time!!

0 Likes
Message 10 of 14

CodeDing
Advisor
Advisor
(defun :member (main lst / cnt)
  (setq cnt 0)
  (foreach x main
    (if (member x lst)
      (setq cnt (1+ cnt))
    );if
  );foreach
  (if (< cnt 3) t)
);defun

 

(defun c:TEST ( / myList)
  (setq myList (list
    '((4 2 2 4) (2 3))
    '((4 2 2 4) (4 3))
    '((4 2 2 2 5) (4 5 6 7))
    '((4 4 2 2 2 4) (4 5 6 7))
    '((4 2 2 4 3) (4 3))
  ))
  (foreach x myList
    (terpri)
    (princ (:member (car x) (cadr x)))
  )
  (princ)
)

Returns:

 

Command: TEST
T
T
T
nil
nil

 

 

 

 

Message 11 of 14

doaiena
Collaborator
Collaborator

The problem with checking the counter with (< cnt 3), is that it will return true when 0. Both lists could have no common member, but the function will return true.

Message 12 of 14

CodeDing
Advisor
Advisor

WHOOPS!

Great Catch

This would be the fix:

(if (< 0 cnt 3) t)

 

Message 13 of 14

ronjonp
Mentor
Mentor

Just a tiny detail but no need to wrap that check in an IF statement:

(< 0 cnt 3)
Message 14 of 14

ronjonp
Mentor
Mentor

@Anonymous 

What would you expect to return with a list like this?

'(4 3 2 4 ) '(4 3)

 

0 Likes