📜  LISP-设置

📅  最后修改于: 2020-11-03 07:17:05             🧑  作者: Mango


Common Lisp不提供设置的数据类型。但是,它提供了许多功能,可以对列表执行设置操作。

您可以根据各种条件在列表中添加,删除和搜索项目。您还可以执行各种设置操作,例如:并集,交集和设置差。

在LISP中实现集

像列表这样的集合通常是根据con单元实现的。但是,由于这个原因,集合越大,集合操作的效率就越低。

伴随函数使您可以构建集合。它接受一个项目和一个代表集合的列表,并返回一个代表该集合的列表,其中包含该项目和原始集合中的所有项目。

adjoin函数首先在给定列表中查找项目,如果找到,则返回原始列表;否则,它将创建一个新的cons单元格,其汽车作为商品, cdr指向原始列表,并返回此新列表。

adjoin函数还带有:key:test关键字参数。这些参数用于检查项目是否存在于原始列表中。

由于adjoin函数不会修改原始列表,因此要更改列表本身,必须将adjoin返回的值分配给原始列表,或者可以使用宏pushnew将一个项目添加到集合中。

创建一个名为main.lisp的新源代码文件,然后在其中键入以下代码。

; creating myset as an empty list
(defparameter *myset* ())
(adjoin 1 *myset*)
(adjoin 2 *myset*)

; adjoin did not change the original set
;so it remains same
(write *myset*)
(terpri)
(setf *myset* (adjoin 1 *myset*))
(setf *myset* (adjoin 2 *myset*))

;now the original set is changed
(write *myset*)
(terpri)

;adding an existing value
(pushnew 2 *myset*)

;no duplicate allowed
(write *myset*)
(terpri)

;pushing a new value
(pushnew 3 *myset*)
(write *myset*)
(terpri)

当您执行代码时,它返回以下结果-

NIL
(2 1)
(2 1)
(3 2 1)

检查会员

函数的成员组使您可以检查元素是否为集合的成员。

以下是这些函数的语法-

member item list &key :test :test-not :key 
member-if predicate list &key :key 
member-if-not predicate list &key :key

这些功能在给定列表中搜索满足测试要求的给定项目。如果找不到此类项目,则函数返回nil。否则,将返回以元素为第一个元素的列表的末尾。

搜索仅在顶层进行。

这些函数可以用作谓词。

创建一个名为main.lisp的新源代码文件,然后在其中键入以下代码。

(write (member 'zara '(ayan abdul zara riyan nuha)))
(terpri)
(write (member-if #'evenp '(3 7 2 5/3 'a)))
(terpri)
(write (member-if-not #'numberp '(3 7 2 5/3 'a 'b 'c)))

当您执行代码时,它返回以下结果-

(ZARA RIYAN NUHA)
(2 5/3 'A)
('A 'B 'C)

设置联盟

函数的联合组允许您在测试的基础上对作为这些函数的参数提供的两个列表执行集合联合。

以下是这些函数的语法-

union list1 list2 &key :test :test-not :key 
nunion list1 list2 &key :test :test-not :key

union函数采用两个列表,并返回一个新列表,其中包含两个列表中任何一个中存在的所有元素。如果有重复项,则成员的一个副本仅保留在返回的列表中。

nunion函数执行相同的操作,但可能会破坏参数列表。

创建一个名为main.lisp的新源代码文件,然后在其中键入以下代码。

(setq set1 (union '(a b c) '(c d e)))
(setq set2 (union '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch)
)
       
(setq set3 (union '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)))
)
(write set1)
(terpri)
(write set2)
(terpri)
(write set3)

当您执行代码时,它返回以下结果-

(A B C D E)
(#(F H) #(5 6 7) #(A B) #(G H))
(#(A B) #(5 6 7) #(F H) #(5 6 7) #(A B) #(G H))

请注意

对于三个向量的列表,如果没有:test-not#’mismatch参数,则union函数无法按预期工作。这是因为列表是由cons单元组成的,尽管值看上去对我们来说显然相同,但是单元的cdr部分不匹配,因此它们与LISP解释器/编译器并不完全相同。这就是原因;建议不要使用列表来实现大型集合。不过,它适用于小型设备。

设置相交

函数的交集组允许您在测试的基础上对作为这些函数的参数提供的两个列表执行交集。

以下是这些函数的语法-

intersection list1 list2 &key :test :test-not :key 
nintersection list1 list2 &key :test :test-not :key

这些函数采用两个列表,并返回一个新列表,其中包含两个参数列表中存在的所有元素。如果任一列表中都有重复的条目,则冗余条目可能会或可能不会出现在结果中。

创建一个名为main.lisp的新源代码文件,然后在其中键入以下代码。

(setq set1 (intersection '(a b c) '(c d e)))
(setq set2 (intersection '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch)
)
       
(setq set3 (intersection '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)))
)
(write set1)
(terpri)
(write set2)
(terpri)
(write set3)

当您执行代码时,它返回以下结果-

(C)
(#(A B) #(5 6 7))
NIL

相交函数是相交的破坏性版本,即,它可能会破坏原始列表。

设置差异

函数组的差异设置允许您在测试的基础上,对作为这些函数的参数提供的两个列表执行差异设置。

以下是这些函数的语法-

set-difference list1 list2 &key :test :test-not :key 
nset-difference list1 list2 &key :test :test-not :key

设置差异函数将返回第一个列表中未出现在第二个列表中的元素的列表。

创建一个名为main.lisp的新源代码文件,然后在其中键入以下代码。

(setq set1 (set-difference '(a b c) '(c d e)))
(setq set2 (set-difference '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch)
)
(setq set3 (set-difference '(#(a b) #(5 6 7) #(f h)) 
   '(#(5 6 7) #(a b) #(g h)))
)
(write set1)
(terpri)
(write set2)
(terpri)
(write set3)

当您执行代码时,它返回以下结果-

(A B)
(#(F H))
(#(A B) #(5 6 7) #(F H))