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

时间:2010-09-22 05:29:25

标签: lisp

我试图弄清楚如何在可能的嵌套列表中找到重复的原子。我一整天都想弄清楚这一点。如果你可以请给我逻辑,这将是伟大的,因为我真的想学习。

基本上

(findDup '(a b b))将返回t

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

5 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

这应该照顾第一种情况:

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

答案 3 :(得分:0)

如果列表为空/没有原子car,那么你去(例如(car (car (car ...)))递归),那么答案是错误的。

您想要找到列表的第一个原子,并查看该原子是否出现在列表中的任何其他位置。您可以使用像member-of?这样的函数来做到这一点 - 在 The Little Schemer 中讨论类似的东西,但基本上你只是测试列表中的所有原子,并重复列表, 反对那个原子。

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

否则,您将再次使用列表的cdr重试(重复)。

答案 4 :(得分:0)

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

然后,以下伪代码应该足够了:

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.