我一直在寻找一种有效的方法来删除点列表中的连续重复项。
我最初的想法是循环遍历列表的元素,与第 (n-1) 个元素进行比较,如果相等则将其删除。但是,删除列表中的元素并不简单,使用另一个函数会降低效率。
我知道 Lee Mac 的 RemoveOnce函数,但我不知道如何修改它以在列表的连续元素之间进行比较。
作为示例,目标如下:
List = (p1 p2 p3 p3 p3 p2 p2 p4)
List_without_consecutive_duplicates = (p1 p2 p3 p2 p4)
谢谢!
最佳答案
这是一个迭代方法:
(defun remcondupes ( l / r )
(while l
(if (not (equal (car l) (cadr l) 1e-8))
(setq r (cons (car l) r))
)
(setq l (cdr l))
)
(reverse r)
)
这是一个递归方法:
(defun remcondupes ( l )
(if l
(if (equal (car l) (cadr l) 1e-8)
(remcondupes (cdr l))
(cons (car l) (remcondupes (cdr l)))
)
)
)
在上述两个例子中,使用 equal
函数将列表中的第一个元素与第二个元素进行比较,容差为 1e-8
(因为我们是比较点),如果此测试有效,则丢弃第一个元素。
测试:
_$ (setq p1 '(1.2 2.3) p2 '(3.4 4.5) p3 '(5.6 6.7) p4 '(7.8 8.9))
(7.8 8.9)
_$ (setq lst (list p1 p2 p3 p3 p3 p2 p2 p4))
((1.2 2.3) (3.4 4.5) (5.6 6.7) (5.6 6.7) (5.6 6.7) (3.4 4.5) (3.4 4.5) (7.8 8.9))
_$ (remcondupes lst)
((1.2 2.3) (3.4 4.5) (5.6 6.7) (3.4 4.5) (7.8 8.9))
编辑:
或者,为了在比较容差内依次考虑连续点(根据下面 Will 的评论),您可以考虑以下变体:
(defun remcondupes ( l / r )
(while l
(if (equal (car l) (cadr l) 1e-8)
(setq l (cons (car l) (cddr l)))
(setq r (cons (car l) r)
l (cdr l)
)
)
)
(reverse r)
)
(defun remcondupes ( l )
(if l
(if (equal (car l) (cadr l) 1e-8)
(remcondupes (cons (car l) (cddr l)))
(cons (car l) (remcondupes (cdr l)))
)
)
)
关于lisp - AutoLISP:删除列表中的连续重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66104836/