Tree 带子元素的嵌套列表元素的Lisp位置

Tree 带子元素的嵌套列表元素的Lisp位置,tree,common-lisp,indexof,Tree,Common Lisp,Indexof,假设我们有以下列表: (A B C D) 我们可以通过以下方式找到C的索引: (position 'C '(A B C D)) 但是,如果其中一个列表元素与其自己的子元素嵌套: (position 'B '(A (B 1 2 (3 x y z)) C D)) 该函数将产生NIL 我们如何在这样的嵌套列表中有效地定位元素的n位置,特别是如果原子位于子列表中,例如y - 以下是我迄今为止的尝试: 当元素被发现在树的某个深层时,它的位置应该是什么还不是很清楚 一种可能是返回与元素对应的第n个叶的

假设我们有以下列表:

(A B C D)
我们可以通过以下方式找到
C
的索引:

(position 'C '(A B C D))
但是,如果其中一个列表元素与其自己的子元素嵌套:

(position 'B '(A (B 1 2 (3 x y z)) C D))
该函数将产生
NIL

我们如何在这样的嵌套列表中有效地定位元素的
n
位置,特别是如果原子位于子列表中,例如
y

以下是我迄今为止的尝试:
当元素被发现在树的某个深层时,它的位置应该是什么还不是很清楚

一种可能是返回与元素对应的第n个叶的索引

在这种情况下,例如,给定一个函数,您可以编写如下函数:

(defun my-position (elm tree)
  (position elm (flatten tree))
另一种可能性是将索引的概念推广到树结构,例如,通过返回一个列表,其中位置j中的元素是元素的位置,或者包含它的列表位于级别j。例如:

(my-position 'A '(A (B 1 2 (3 x y z)) C D)) => (0)
(my-position 'B '(A (B 1 2 (3 x y z)) C D)) => (1 0)
(my-position 'y '(A (B 1 2 (3 x y z)) C D)) => (1 3 2)
在这种情况下,递归函数可以是:

(defun my-position (elm tree &optional (start 0))
  "find the generalized position of elm inside tree.
   Parameters: elm - element to be found
               tree - a list of atoms and lists in which to search the element
               start - the tentative position"      
  (cond ((null tree) nil)       ; element not present => nil
        ((atom (first tree))    ; if the first element is an atom, then
         (if (eql elm (first tree)) ; if equal to element, found
             (list start)           ; return position start
             ;; otherwise, recur on rest of list incrementing the tentative position
             (my-position elm (rest tree) (1+ start))))
        ;; otherwise, the first element is a list,
        ;; try to find it inside, with a recursive call
        (t (let ((pos (my-position elm (first tree) 0)))
             (if pos ; if not nil the element has been found
                 (cons start pos) ; return the current position followed by the position inside the list
                 ; otherwise recur on rest of list incrementing the tentative position
                 (my-position elm (rest tree) (1+ start)))))))

最后一点注意:要编写更“专业”的函数,应添加预定义的关键字参数。

没有内置函数。你需要写一个。如果是一个内部对象,比如上面例子中的y,结果会是什么?可能有几种不同的可能性。嗯。。。可能是一个cons单元格,其中包含子列表中的
id
,以及该列表中的父项。因此,以
y
为例,它将是:
(2·3)
酷!你能解释一下你的代码吗?我真的不能理解这些条件。@Sati,我修改了答案。谢谢!解释很清楚。有一个问题:
t
pos
(t(let((pos(我的位置elm(第一棵树)0))
中做了什么?您正在使用
let
将列表中第一个元素的位置设置为
0
,如果我没有错的话?不,看看外部
cond
,它有三个分支:
(cond)((空树)…返回nil…((atom(first tree))…当列表的第一个元素不是列表时管理列表…(t(…否则……当列表的第一个元素是列表时管理列表…)
。换句话说,
t
这里的意思是:当前两个案例为false,并且对应于“否则”(或者if-then-elsif链中的最终else…)在其他语言中。通常是的。除非所有其他条件涵盖所有可能的情况。
(defun my-position (elm tree &optional (start 0))
  "find the generalized position of elm inside tree.
   Parameters: elm - element to be found
               tree - a list of atoms and lists in which to search the element
               start - the tentative position"      
  (cond ((null tree) nil)       ; element not present => nil
        ((atom (first tree))    ; if the first element is an atom, then
         (if (eql elm (first tree)) ; if equal to element, found
             (list start)           ; return position start
             ;; otherwise, recur on rest of list incrementing the tentative position
             (my-position elm (rest tree) (1+ start))))
        ;; otherwise, the first element is a list,
        ;; try to find it inside, with a recursive call
        (t (let ((pos (my-position elm (first tree) 0)))
             (if pos ; if not nil the element has been found
                 (cons start pos) ; return the current position followed by the position inside the list
                 ; otherwise recur on rest of list incrementing the tentative position
                 (my-position elm (rest tree) (1+ start)))))))