LISP 中的集合
集合是项目的无序集合。集合就像其他数据结构一样。在 C++ 中,我们有一个类似的数据结构,称为哈希映射。 Common lisp 不提供内置的集合数据类型,但它提供了许多允许对列表执行集合操作的函数。使用它们,我们可以在列表中添加和删除项目,还可以检查列表中是否存在项目。我们还可以对列表进行并、交、差运算。
在 Lisp 中实现集合:
集合是使用adjoin函数实现的。 Adjoin函数允许我们建立一个集合。 Adjoin函数可以将列表作为参数并返回一个集合。邻接函数定义如下:
句法:
adjoin item list &key key test => new-list
这里,item 是一个对象,list 是一个正确的列表,test 是一个有两个参数的函数的指示符,它返回一个布尔值,key 是一个有一个参数的函数的指示符函数。
这些键和测试参数用于检查列表中是否存在项目。如果该项目存在于列表中,则该项目不会添加到集合中。如果该项目不在列表中,则将该项目添加到集合中。如果集合中不存在该项目,我们可以使用宏pushnew将项目添加到集合中,并使用 DELETE 或 REMOVE 删除或删除该项目。
例子:
创建一个新的 lisp 文件并将其保存为set.lisp
Lisp
;; Implementing the Sets in the Lisp
(defparameter *mynewset* ()) ;; empty set
(adjoin 1 *mynewset*) ;; *mynewset* is now (1)
(adjoin 2 *mynewset*) ;; *mynewset* is now (1 2)
; adjoin did not change the original set
; so it remains same
(write *mynewset*) ;; (1 2)
(terpri) ;; prints a new line
(setf *mynewset* (adjoin 1 *mynewset*)) ;; *mynewset* is now (1)
(setf *mynewset* (adjoin 2 *mynewset*)) ;; *mynewset* is now (1 2)
; adding an existing value
(pushnew 2 *mynewset*) ;; *mynewset* is now (1 2)
; no duplicate allowed
(write *mynewset*) ;; (1 2)
(terpri) ;; prints a new line
; pushing a new value
(pushnew 3 *mynewset*) ;; *mynewset* is now (1 2 3)
(write *mynewset*) ;; (1 2 3)
(terpri) ;; prints a new line
Lisp
;; Checking Membership in a Set
(write (member 0 (list 1 2 3))) ;; returns nil
(terpri) ;; prints a new line
(write (member-if #'evenp '(5 7 9 8 4 ) ));; returns t
(terpri) ;; prints a new line
(write (member-if-not #'numberp '(3 7 2 5/3 'not 'number ))) ;; returns nil
Lisp
;; Set union in Lisp
(setq set1 (union '(1 2 3) '(2 3 4))) ;; set1 is (1 2 3 4)
(terpri) ;; prints a new line
(setq set2 (union '(a b 5 6 7 f h) '(5 6 7 a b g h)))
(write set1) ;; (1 2 3 4)
(terpri)
(write set2) ;; (F 5 6 7 A B G H)
(terpri)
Lisp
;; Set intersection in Lisp
(setq set1 (intersection '(1 2 3) '(2 3 4))) ;; set1 is (2 3)
(terpri) ;; prints a new line
(setq set2 (intersection '(a b 5 6 7 f h) '(5 6 7 a b g h)))
(write set1) ;; (2 3)
(terpri) ;; prints a new line
( write set2) ;; (A B 5 6 7 H)
(terpri) ;; prints a new line
Lisp
;; Set Difference in Lisp
(write(setq lst1 (list "A" "b" "C" "d") lst2 (list "a" "B" "C" "d")))
;; lst1 is ("A" "b" "C" "d") lst2 is ("a" "b" "C" "d")
(write(set-difference lst1 lst2)) ;; returns ("A" "C")
(terpri) ;; prints a new line
(write(set-difference lst1 lst2 :test 'equal)) ;; returns ("A" "C")
(terpri) ;; prints a new line
(write(nset-difference lst1 lst2 :test #'string=));; returns ("A" "b" "C" "d")
(terpri) ;; prints a new line
输出:
检查集合中的成员资格:
Membership 是一个检查一个项目是否存在于集合中的函数。隶属函数定义如下:
member item list &key :test :test-not :key
member-if predicate list &key :key
member-if-not predicate list &key :key
这些函数探测项目的列表。如果该项目存在于列表中,则隶属函数返回 t。如果该项目不在列表中,则隶属函数返回 nil。搜索仅在顶层完成。搜索按列表顺序进行。
句法:
member item list test &key key &key => tail or nil
这里的item是要查找的item,list是要查找的list,test是要比较的item, &key是函数键。 Key 是用于在测试前提取值的函数。成员函数在列表中搜索项目。如果该项目存在于列表中,则隶属函数返回 t。如果该项目不在列表中,则隶属函数返回 nil。搜索仅在顶层完成。搜索按列表顺序进行。
例子:
创建一个新的lisp 文件并将其保存为membership.lisp。
语言
;; Checking Membership in a Set
(write (member 0 (list 1 2 3))) ;; returns nil
(terpri) ;; prints a new line
(write (member-if #'evenp '(5 7 9 8 4 ) ));; returns t
(terpri) ;; prints a new line
(write (member-if-not #'numberp '(3 7 2 5/3 'not 'number ))) ;; returns nil
输出:
在 Lisp 中设置联合:
并集表示列表中所有项目的集合。使用并集函数,我们可以找到两个集合的并集。联合函数定义如下:
句法:
union list1 list2 &key :test
nunion list1 list2 &key :test
在这里,union函数接受两个列表 list1 和 list2,并返回一个新列表,其中包含两个列表中的所有项目。新列表中不允许有重复项。
例子:
创建一个新的 lisp 文件并将其保存为union.lisp。
语言
;; Set union in Lisp
(setq set1 (union '(1 2 3) '(2 3 4))) ;; set1 is (1 2 3 4)
(terpri) ;; prints a new line
(setq set2 (union '(a b 5 6 7 f h) '(5 6 7 a b g h)))
(write set1) ;; (1 2 3 4)
(terpri)
(write set2) ;; (F 5 6 7 A B G H)
(terpri)
输出:
在 Lisp 中设置交集:
交集可以认为是两个集合共有的项目集合。要进行交集,我们可以使用交集函数组。它需要两个列表并返回一个新列表,其中包含两个列表共有的所有项目。交集函数定义如下:
句法:
intersection list1 list2 &key :test
nintersection list1 list2 &key :test
这里的交集函数接受两个列表,list1 和 list2,并返回一个新列表,其中包含两个列表共有的所有项目。交集与交集函数相同,只是它使用其单元格破坏 list1 以构造结果 list2 并返回结果 list2。
例子:
创建一个新的 lisp 文件并将其保存为intersection.lisp。
语言
;; Set intersection in Lisp
(setq set1 (intersection '(1 2 3) '(2 3 4))) ;; set1 is (2 3)
(terpri) ;; prints a new line
(setq set2 (intersection '(a b 5 6 7 f h) '(5 6 7 a b g h)))
(write set1) ;; (2 3)
(terpri) ;; prints a new line
( write set2) ;; (A B 5 6 7 H)
(terpri) ;; prints a new line
输出:
在 Lisp 中设置差异:
集合差异是在第一个集合中但不在第二个集合中的项目集合。使用集差函数,我们可以找到两个集合的集差。集合差分函数定义如下:
句法:
set-difference list1 list2 &key :test
nset-difference list1 list2 &key :test
在这里,设置差异函数接受两个列表,list1 和 list2,并返回一个新列表,其中包含第一个列表中但第二个列表中没有的所有项目。 nset-difference 与 set Difference函数相同,只是它使用其单元格破坏 list1 以构造结果 list2 并返回结果 list2。
Set-difference 返回第一个列表中但不在第二个列表中的项目列表。
Nset是 set-difference 的破坏性版本,它破坏 list1 并返回结果 list2。
例子:
创建一个新的 lisp 文件并将其保存为set-difference.lisp。
语言
;; Set Difference in Lisp
(write(setq lst1 (list "A" "b" "C" "d") lst2 (list "a" "B" "C" "d")))
;; lst1 is ("A" "b" "C" "d") lst2 is ("a" "b" "C" "d")
(write(set-difference lst1 lst2)) ;; returns ("A" "C")
(terpri) ;; prints a new line
(write(set-difference lst1 lst2 :test 'equal)) ;; returns ("A" "C")
(terpri) ;; prints a new line
(write(nset-difference lst1 lst2 :test #'string=));; returns ("A" "b" "C" "d")
(terpri) ;; prints a new line
输出: