damonkashu
damonkashu

Reputation: 1823

Is there a common LISP function to compare the contents of two lists?

In particular, I just want to ensure that two lists have the same elements, ignoring order

Upvotes: 12

Views: 16965

Answers (7)

user4813927
user4813927

Reputation:

(defun list= (l1 l2 &key (test #'eql))
  (loop for i in l1
     for j in l2
     always (funcall test i j)))


(list= '(1 2 "a") '(1 2 "a") :test #'equal) ;; => T
(list= '(1 2 "a") '(1 2 "a") :test #'eql) ;; => NIL

Upvotes: 1

Amir Shareghi
Amir Shareghi

Reputation: 15

If the order isn't important you can use "equal-set":

(equal-sets (1 2)(1 2)) -> T

(equal-sets (1 2)(2 1)) -> T

(equal-sets (1 2 5)(1 2)) -> NIL

(equal-sets (1 2)(1 5 2)) -> NIL

Upvotes: -1

Jack Kelly
Jack Kelly

Reputation: 18667

Sort both lists, then compare:

(equal (sort l1 #'<) (sort l2 #'<))

Upvotes: 0

philosodad
philosodad

Reputation: 1808

According to Steele "set-difference returns a list of elements of list1 that do not appear in list2. This operation is not destructive."

So if the set-difference is empty and the lengths are the same...

http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node152.html#SECTION001950000000000000000

Upvotes: 1

huaiyuan
huaiyuan

Reputation: 26539

(defun same-bag-p (bag1 bag2 &key (test #'eql))
  (let ((table (make-hash-table :test test)))
    (loop for key in bag1 do (incf (gethash key table 0)))
    (loop for key in bag2 do (decf (gethash key table 0)))
    (loop for val being each hash-value of table always (= val 0))))

Upvotes: 4

Rainer Joswig
Rainer Joswig

Reputation: 139261

If repeating items are not important see also SET-EXCLUSIVE-OR.

Upvotes: 3

Steve Rowe
Steve Rowe

Reputation: 19413

If order isn't important, you can use equal. For instance,

(equal (list 1 2) (list 1 2))

is true. Thus one way to do it would be to (sort) the list and then use equal. Note that sort is destructive so if order matters, you might want to copy it first.

Upvotes: 9

Related Questions