List comparison function troubles

List comparison function troubles

Michiel.Valcke
Advisor Advisor
557 Views
4 Replies
Message 1 of 5

List comparison function troubles

Michiel.Valcke
Advisor
Advisor

Dear master lispers, 

I need help, I can't find my mistake and it's driving me crazy

 

As part of a larger routine I need a routine that can tell me if two supplied lists are the same. the supplied lists can consist of strings/integers/reals or other lists (also definitely dotted pair lists)

 

The routine needs a flag because sometimes I just need to check if both lists have the same members (if even in multiple occurences) and other times I will need to check very precisely that both lists have the same members in the same order 

 

I wrote the below routine. It sorts on flag, if the flag is given. It does a member check for one list against the other and vice versa, and will check the resulting list to see if there is a nil value in there, the routine will output nil or T accordingly. This has been tested and seems to work fine (it could be more efficient by not relying so heavily on the member function, but that would be an issue for later)

 

If the flag is not set, the comparison has to be precise, the position of the members need to correspond, each member needs to have a corresponding member in the corresponding position in the other list. In case that member is a list, its content also needs to match.

 

I decided to split the checks in different checks figuring that if any check is failed I can set the output to nil and move on with my life ^^ 

 

 

(defun CompareList ( l1 l2 flag / r cnt)
  ; take two lists
  ; get flag 
  ; check if each list has the same members as the other
  ; if flag is not nil, list order & duplicity is not followed
  ; return T if lists are the same, return nil if lists are not the same
  (if flag
    (progn
      (foreach m l1 
        (setq r (cons (member m l2) r))
      )
      (foreach m l2
        (setq r (cons (member m l1) r))
      )
      (if
        (member nil r)
        (setq r nil)
        (setq r T)
      )
    ) ; do this if flag is not nil
    (progn
      (if
        (= (length l1) (length l2))
        (progn 
          (setq cnt 0
                r T)
          (while 
            (and (< cnt (length l1)) r)
            (cond
              ((/= (type (nth cnt l1)) (type (nth cnt l2))) (setq r nil)) ; check if member type is the same
              ((= (type (nth cnt l1)) "LIST") (if (not (CompareList (nth cnt l1) (nth cnt l2) nil))(progn (setq r nil)))) ; if it is a list, repeat CompareList
              ((/= (type (nth cnt l1)) "LIST") (if (/= (nth cnt l1) (nth cnt l2)) (progn (setq r nil)))) ; if not list, check if the same
            )
            (setq cnt (1+ cnt))
          )
        ) ; if the length of the lists does match -> check others
        (progn
          (setq r nil)
        ) ; if the length of the lists does not match -> nil
      )
    ) 
  ) ; check if flag is set
  r
) ; end of Comparelist

 

(I'm using type checks instead of ltype because I got another error with ltype)

 

When I test the routine with the below code. I get the weird behaviour that when I do (CompareList att1 att1 nil) the routine correctly gives me T

 

But when I compare att1 and att2, though they both are construed in the same way, the routine incorrectly gives me nil.

 

 

(defun c:aaaaaa ( / att1 att2 att3)
  
  (setq att1 (cons (cons 0 "a") att1))
  (setq att1 (cons (cons 1 "b") att1))
  
  (setq att2 (cons (cons 0 "a") att2))
  (setq att2 (cons (cons 1 "b") att2))
  
  (setq att3 (cons (cons 0 "a") att3))
  (setq att3 (cons (cons 2 "c") att3))

  (CompareList att1 att2 nil)
)

 

 

I can't figure it out what I'm missing. I'm hoping one of you might find the error in my code.

Thank you for your time.

0 Likes
Accepted solutions (2)
558 Views
4 Replies
Replies (4)
Message 2 of 5

ВeekeeCZ
Consultant
Consultant
Accepted solution

Ouch!!

 

(= (type (nth cnt l1)) "LIST")

->

(= (type (nth cnt l1)) 'LIST)

Message 3 of 5

martti.halminen
Collaborator
Collaborator
Accepted solution

Then first question this raises: why doesn't normal AutoLISP EQUAL work for you for the exact case?

 

Depending on the structure of the data, the non-exact branch could be done something in the style of

 

(equal (remove-duplicates <test> (vl-sort l1 <comparision-func>)))
       (remove-duplicates <test> (vl-sort l2 <comparision-func>))))

 

the relevant test and comparision functions depend on your data.

Message 4 of 5

Michiel.Valcke
Advisor
Advisor
I completely missed that. definitely a case of tunnel-vision. I'm gonna rewrite the routine using equal, which will be a lot easier. Thank you very much
0 Likes
Message 5 of 5

Michiel.Valcke
Advisor
Advisor

ooh that is painful indeed. But if I apply it I get "; error: bad list: "b"" thrown back at me, so my logic must be way off in some other points as well.

Still thank you very much. I completely looked over it.

0 Likes