繁体   English   中英

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

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

(分配帮助,请放心)(我必须在不使用破坏性函数(setf)的情况下执行此操作)

使用通用Lisp,作为某些代码的一部分,我需要能够:

取得列表列表,比较2个元素的cdr;如果相等,则忽略第一个元素;如果不相等,则尝试将第一个元素与列表中的下一个未经检查的元素进行比较。

一些例子可以澄清:

(((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))

(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))))))

目前,只有当所有“喜欢”字词在列表中并排放置时,代码才能正常工作。

Le Petit Prince在评论中建议使用删除重复项可能是您想要的。 remove-duplicates是非破坏性的(请参阅delete-duplicates可能是破坏性的),它被指定为返回一个新列表,其中省略了除元素的最后一个实例之外的所有其他元素(添加了强调):

删除重复项

remove-duplicates返回序列的修改后的副本,已从该序列中删除了与按顺序出现的另一个元素匹配的任何元素。 …对序列的元素进行成对比较,如果有两个匹配,则丢弃序列中较早出现的一个 ,除非from-end为true,在这种情况下,序列中较晚的一个被丢弃。

您需要指定一个key参数来指示实际上应该比较的是元素的cdr ,以及一个test参数来指示应该将它们与equal比较。 从而:

(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