Существует ли общая функция LISP для сравнения содержимого двух списков? - PullRequest
8 голосов
/ 06 ноября 2010

В частности, я просто хочу убедиться, что два списка имеют одинаковые элементы, игнорируя порядок

Ответы [ 7 ]

7 голосов
/ 06 ноября 2010

Если порядок не важен, вы можете использовать равные. Например,

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

верно. Таким образом, один из способов сделать это состоит в том, чтобы (отсортировать) список, а затем использовать равные. Обратите внимание, что сортировка деструктивна, поэтому, если порядок имеет значение, вы можете сначала скопировать его.

4 голосов
/ 06 ноября 2010
(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))))
2 голосов
/ 06 ноября 2010

Если повторяющиеся элементы не важны, см. Также SET-EXCLUSIVE-OR.

1 голос
/ 13 октября 2013

Если порядок не важен, вы можете использовать «равный набор»:

(равный набор (1 2) (1 2)) -> T

(равный набор(1 2) (2 1)) -> T

(равные множества (1 2 5) (1 2)) -> NIL

(равные множества (1 2) (1 5 2)) -> NIL

1 голос
/ 06 ноября 2010

По словам Стила "set-diff возвращает список элементов list1, которые не появляются в list2. Эта операция не является разрушительной."

Так что, если разность наборов пуста, а длины одинаковы ...

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

0 голосов
/ 08 ноября 2018
(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
0 голосов
/ 07 ноября 2010

Сортируйте оба списка, затем сравните:

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