在Common Lisp中找到列表中最嵌套的列表

时间:2011-01-13 16:39:53

标签: lisp common-lisp nested-lists

我是Common Lisp和函数式编程的新手,但我在C,C ++,C#,Java等语言方面有很多经验。我在列表中找到最嵌套的列表时遇到了麻烦。我的意见是这样的:

(0 1 (2 3) 4 (5 (6 (7) 8)) 9)

我想在这个列表中获得最嵌套的列表,在这种情况下是

(7)

我确实有一个想法,我可以以某种方式压扁列表,直到只剩下一个子列表。为了说明我的意思,这里有几个步骤:

步骤1. - 输入:

(0 1 (2 3) 4 (5 (6 (7) 8)) 9)

步骤2. - 展平“第一级”:

(0 1 2 3 4 5 (6 (7) 8) 9)

步骤3. - 在“第二级”上展平:

(0 1 2 3 4 5 6 (7) 8 9)

现在只剩下一个嵌套列表,这意味着这是最嵌套的列表。但是我发现这里有两个或更多这样的列表会出现问题。请分享您对此的看法。

我在Common Lisp中将此过程变为现实时遇到了问题,所以我会感谢一些正确方向的指针,可能是一些示例代码等等。这是一项家庭作业,所以我并不期望有一个完整的解决方案,但如果有人指出可能是一个更简单,更好的解决方案及其实施,那就很高兴。

3 个答案:

答案 0 :(得分:3)

这是我的解决方案,使用与OP相似的方法。 (如果有多个最深的项目,则全部退回。)

我在Scheme中写了它,它可能不会立即翻译成Common Lisp,所以我觉得它不是一个完整的赠品。尽管如此,它仍有可能变得乏味,所以谨慎行事。

(define (deepest lst)
  (let ((filtered (filter pair? lst)))
    (cond ((null? filtered) lst)
          (else (deepest (concatenate filtered))))))

答案 1 :(得分:2)

您对列表进行迭代展平的方法应该可以正常工作,尽管它不是最有效或(主观)优雅的方法。

如果有多个这样的列表,正确的输出将取决于规范 - 如果你返回所有这些,或者只返回第一个,或者抛出错误?

如果我是你,我会考虑提出一个递归功能来解决问题。每个级别的递归基本上都会处理给定级别的嵌套列表的元素。想想每个递归调用应该做什么 - 如果它一次点击就很简单!

答案 2 :(得分:2)

这是我在CL中的(不是很干净)解决方案:

(defun deepest-list (lst)
  (let ((max-depth 0) ret)
    (labels ((inner-deepest-lst (lst depth)
           (cond
         ((null lst) depth)
         ((listp (car lst))
          (let ((local-max (max
                    (inner-deepest-lst (first lst) (1+ depth))
                    (inner-deepest-lst (rest lst)  (1+ depth)))))
            (and (> local-max max-depth) (setf ret (first lst) max-depth local-max))
            local-max))
         (t (inner-deepest-lst (rest lst) depth)))))
      (inner-deepest-lst lst 1))
    ret))

编辑:

经过一番思考,这是一个稍微清洁的解决方案:

(defun deepest-list (lst)
  (labels ((dl (lst depth)
         (cond
           ((atom lst) (cons 0 lst))
           ((every #'atom lst) (cons depth lst))
           (t (funcall (lambda (x y) (if (> (car x) (car y)) x y))
               (dl (car lst) (1+ depth))
               (dl (cdr lst) depth))))))
    (rest (dl lst 0))))