简体   繁体   English

Common Lisp:删除具有相同cdr的元素

[英]Common Lisp: Removing elements with the same cdr

(Assignment help, go easy on me) (I have to do this without using destructive functions (setf)) (分配帮助,请放心)(我必须在不使用破坏性函数(setf)的情况下执行此操作)

With common lisp, as part of some code I need to be able to: 使用通用Lisp,作为某些代码的一部分,我需要能够:

Take a list of lists, compare the cdr of 2 elements, If equal disregard the first element, If not equal then try and compare the first element with the next unchecked element in the list. 取得列表列表,比较2个元素的cdr;如果相等,则忽略第一个元素;如果不相等,则尝试将第一个元素与列表中的下一个未经检查的元素进行比较。

Some examples to clarify: 一些例子可以澄清:

((1 1 1) (2 1 1) (3 1 1)) -> ((3 1 1)) (((1 1 1)(2 1 1)(3 1 1))->(((3 1 1)))

((2 2 0) (4 1 1) (1 2 0) (3 0 1) (8 1 1)) -> ((1 2 0) (3 0 1) (8 1 1)) ((2 2 0)(4 1 1)(1 2 0)(3 0 1)(8 1 1))->(((1 2 0)(3 0 1)(8 1 1))

(defun simplify2 (vari)
    ;If last term: stop
    (if (equal (cdr vari) nil) vari

        ;If cdr of first and second term are equal...
        (if (equal (cdar vari) (cdr (cadr vari)))

            ;Ignore the first term and continue with the rest of the list
            (simplify2 (cdr vari))

            ;Otherwise (this is the line which isn't working)
            (cons (car vari) (simplify2 (cdr vari))))))

At the moment the code will only work properly when all 'like' terms are placed next to each other in the list. 目前,只有当所有“喜欢”字词在列表中并排放置时,代码才能正常工作。

Le Petit Prince's suggestion in the comments to use remove-duplicates is probably what you want here. Le Petit Prince在评论中建议使用删除重复项可能是您想要的。 remove-duplicates is non-destructive (cf. delete-duplicates which can be destructive), and it's specified to a return a new list in which all but the last instance of an element are omitted (emphasis added): remove-duplicates是非破坏性的(请参阅delete-duplicates可能是破坏性的),它被指定为返回一个新列表,其中省略了除元素的最后一个实例之外的所有其他元素(添加了强调):

remove-duplicates 删除重复项

remove-duplicates returns a modified copy of sequence from which any element that matches another element occurring in sequence has been removed. remove-duplicates返回序列的修改后的副本,已从该序列中删除了与按顺序出现的另一个元素匹配的任何元素。 … The elements of sequence are compared pairwise, and if any two match, then the one occurring earlier in sequence is discarded , unless from-end is true, in which case the one later in sequence is discarded. …对序列的元素进行成对比较,如果有两个匹配,则丢弃序列中较早出现的一个 ,除非from-end为true,在这种情况下,序列中较晚的一个被丢弃。

You'll need to specify the a key argument to indicate that what should actually be compared is the cdr of the elements, and a test argument to indicate that they should be compared with equal . 您需要指定一个key参数来指示实际上应该比较的是元素的cdr ,以及一个test参数来指示应该将它们与equal比较。 Thus: 从而:

(remove-duplicates '((1 1 1) (2 1 1) (3 1 1))
                   :test 'equal 
                   :key 'cdr)
;=> ((3 1 1))

(remove-duplicates '((2 2 0) (4 1 1) (1 2 0) (3 0 1) (8 1 1))
                   :test 'equal
                   :key 'cdr)
;=> ((1 2 0) (3 0 1) (8 1 1))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM