In particular, I just want to ensure that two lists have the same elements, ignoring order
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
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.
(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))))
If repeating items are not important see also SET-EXCLUSIVE-OR.
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
(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
Sort both lists, then compare:
(equal (sort l1 #'<) (sort l2 #'<))
(sort (copy-list l1) #'<)
or you should store the result of sort back to l1 and l2. Also this approach requires sortable elements (the hash table one doesn't). –
Saxton 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
© 2022 - 2024 — McMap. All rights reserved.