在LISP中查找可能嵌套的列表中的重复原子

在LISP中查找可能嵌套的列表中的重复原子,lisp,Lisp,我试图找出如何在可能嵌套的列表中找到重复的atom。我一整天都在想这个问题。如果你能告诉我逻辑,那就太好了,因为我真的很想学习 基本上 (findDup'(ab))将返回t (findDup'(a c((d(f a))s))也将返回t最简单、最有效的方法是以下(伪代码): 创建一个数据结构(比如Common Lisp的哈希表)来记住看到了哪些原子 创建一个递归子函数来执行实际的遍历-遍历嵌套列表并将所有新原子添加到数据结构中,如果已有原子,则返回true 如果列表为空/没有原子car(例如,递归

我试图找出如何在可能嵌套的列表中找到重复的atom。我一整天都在想这个问题。如果你能告诉我逻辑,那就太好了,因为我真的很想学习

基本上

(findDup'(ab))
将返回t


(findDup'(a c((d(f a))s))
也将返回t

最简单、最有效的方法是以下(伪代码):

  • 创建一个数据结构(比如Common Lisp的哈希表)来记住看到了哪些原子
  • 创建一个递归子函数来执行实际的遍历-遍历嵌套列表并将所有新原子添加到数据结构中,如果已有原子,则返回true

  • 如果列表为空/没有原子
    car
    (例如,递归地
    (car(car(car…))
    ),则答案为假

    您希望找到列表中的第一个原子,并查看该原子是否出现在列表中的其他任何位置。你可以用一个函数,比如
    成员?
    ——类似的东西在小Schemer中讨论过,但基本上你只需测试列表中的所有原子,,然后在列表中重现,

    如果该原子在列表中,则可以返回true


    否则,您将使用列表中的
    cdr
    重试(继续)

    我从一个包装器函数开始,该函数创建一个哈希表,并将哈希表和列表传递给第二个函数(或者,如果您使用的是Common Lisp,则使用
    &optional
    参数)

    那么,下面的伪代码就足够了:

    If we're looking at an empty list, there are no duplicates
    If the head is a list, we can return the logical OR of "inspect the head" and "inspect the tail"
    If the head is an atom, it's a duplicate if it's already in the hash table. If not, add it to the hash table and inspect the tail for duplicates.
    

    这应考虑到第一种情况:

    (defun find-duplicates (lst)
      (let ((h (make-hash-table))
            (dupes))
        (mapcar #'(lambda (x)
            (if (gethash x h)
                  (push x dupes)
                  (setf (gethash x h) t)))
            lst)
        dupes))
    

    如果列表已排序或可以排序,这是一个简单的解决方案:

    (defun find-duplicates (lst)
       (let ((dup-list nil))
          (sort lst)
          (mapcon (lambda (l) (when (eq (car l) (cadr l)) (push (car l) dup-list))) lst)
          dup-list ))