set-difference作为筛选函数工作,但只用于列表。数组和字符串是什么?这些类型的数据是否有类似的函数?如果没有这样的功能,实现这些功能的适当方式是什么?
现在,我使用这个宏将任何序列作为列表处理(有时它很有用):
(defmacro treat-as-lists (vars &body body)
(let ((type (gensym)))
`(let ((,type (etypecase ,(car vars)
(string 'string)
(vector 'vector)
(list 'list)))
,@(mapcar (lambda (x) `(,x (coerce ,x 'list)))
vars))
(coerce (progn ,@body) ,type))))我的filter
(defun filter (what where &key key (test #'eql))
(treat-as-lists (what where)
(set-difference where what :key key :test test)))示例:
CL-USER> (filter "cat" "can you take this cat away?")
"n you ke his wy?"
CL-USER> (filter #(0 1) #(1 5 0 1 9 8 3 0))
#(5 9 8 3)发布于 2014-06-20 13:23:52
由于编写在所有序列类型上工作的函数通常意味着为列表和向量编写单独的版本,因此在可能的情况下使用在序列上操作的标准函数是值得的。在这种情况下,我们可以使用位置和移除-如果。我颠倒了你们论点的顺序,以便使这个序列差更像集差,其中第二个参数被从第一个参数中减去。
(defun sequence-difference (seq1 seq2 &key (start1 0) end1 (start2 0) end2
key (key1 key) (key2 key)
test test-not)
"Returns a new sequence of the same type of seq1 that contains the
elements of the subsequence of seq1 designated by start1 and end1, and
in the same order, except for those that appear in the subsequence of
seq2 designated by start2 and end2. Test and test-not are used in the
usual way to elements produced by applying key1 (which defaults to
key) to elements from seq1 and by applying key2 (which defaults to
key) to elements from seq2."
(flet ((in-seq2 (x)
(not (null (position x seq2
:start start2 :end end2
:key key2
:test test :test-not test-not)))))
(remove-if #'in-seq2
(subseq seq1 start1 end1)
:key key1)))(sequence-difference "can you take this cat away?" #(#\c #\a #\t))
;=> "n you ke his wy?"
(sequence-difference "can you take this cat away?" #(#\c #\a #\t) :start1 3 :start2 1)
" you ke his c wy?"请注意,该标准还包括发现,它适用于任意序列,但查找返回“序列的一个元素,或为零”。如果零是序列中的一个成员,这将导致歧义。而Position则返回一个索引(它将是一个数字,因此不是null)或null,这样我们就可以可靠地确定一个元素是否是一个按顺序排列的元素。
这里有一个重要的区别,那就是你总是在这里得到一份副本。其原因是主观的:由于序列函数通常采用开始和结束索引参数,因此在这里包含该功能是很好的。但是,如果我们请求(sequence-difference "foobar" "boa" :start1 2),那么我们希望从“foobar”的子序列"obar“中移除b、o和a字符。不过,我们应该返回什么呢?"for“还是"r"?也就是说,我们是否包括seq1中在索引之外的部分?在这个解决方案中,我决定不做,因此我正在做(remove-if … (subseq seq1 …) …),而subseq总是复制。另一方面,如果适当的话,Set-difference可以返回它的list-1或list-2参数.这个实现通常不会返回seq1或seq2,除非在一些病态的情况下(例如,空列表)。
https://stackoverflow.com/questions/24323753
复制相似问题