Lisp - 从位置移除

时间:2013-03-11 22:35:46

标签: position lisp sublist removeall

我需要一个函数来删除起始列表和所有子列表中第n个位置的元素。我不需要工作代码,我只需要任何建议。

3 个答案:

答案 0 :(得分:3)

寻求建议而非最终解决方案值得称赞。我会试着向你解释一下。

单链表可以从前到后递归处理。您可以通过廉价操作获取列表的第一个元素,其余部分,并通过在前面放置一个新元素来构建列表。一个简单的递归方案是:从列表中取出第一个元素,用它做一些事情,然后将它放在结果的前面,用列表的其余部分重复整个过程。连续元素和休止符的重复过程是递归部分。如果您有一个空输入列表,则无需执行任何操作,并返回空列表,从而结束处理。这是您的基本案例,锚点或任何您想要调用它的内容。记住:递归案例,基本案例,检查 - 你需要两者。

(由于Lisp的评估规则,实际上将处理后的元素放在处理后的休息之前,必须记住它,直到其余部分被实际处理,因为构建列表的操作在返回新列表之前评估它的两个参数。这些中间结果将保留在堆栈中,这可能是大型列表的一个问题。有一些方法可以避免这种情况,但我们会在这里保持简单。)

现在,您实际上不仅要求简单列表,还要求树木。方便地,该树被表示为嵌套列表,因此除了一点复杂之外,通常上述仍然适用:您将必须检查您要处理的元素本身是否是分支,即列表。如果是,整个过程也必须在该分支上完成。

基本上就是这样。现在,要从树中删除元素,您的操作只是检查您的元素是否匹配,如果是,则删除它。更详细:

  • 要从空列表中删除元素,只需返回一个空列表。

  • 如果第一个元素本身就是一个列表,则返回从第一个元素构建的列表,其中所有匹配项都作为第一个元素被删除,其余匹配项将被删除。

  • 如果第一个元素匹配,则返回列表的其余部分 匹配元素已删除。 (请注意,此处的内容会被“删除”。)

  • 否则,返回从第一个元素构建的列表作为其第一个元素以及列表的其余部分,并删除所有机械元素。

看看这个,并尝试找到你的递归案例,基本案例,以及处理嵌套树结构的步骤。如果您了解所有这些,那么实施将很容易。如果你从来没有真正学到这一切,并且你的脑袋现在还没有旋转,那就认为自己是一个天生的Lisp程序员。否则,递归只是第一次难以掌握的基本概念,但一旦点击,就像骑自行车一样。

爱德华:不知怎的错过了“位置”部分,并且误读了 - 即使问题标题。这就是疲劳对人们的影响。

无论如何,如果你想按位置删除树中的元素,你可以让你的函数采用可选的计数器参数(或者你可以使用提供它的包装函数)。如果你看一下上面的几点,那么重新计算一个新分支就会重置你的计数器。基本递归方案保持不变,但不是比较元素本身,而是检查计数器 - 如果它与要删除的位置匹配,则删除元素。在每个递归的情况下,你将函数传递给递增的计数器,除非进入一个新的分支,你重置它,即为你的计数器参数传递0。 (一旦删除元素,你也可以返回列表的其余部分,使函数更高效,特别是对于要删除开头附近元素的长列表,但是让我们在这里保持简单。)

答案 1 :(得分:1)

我的方法如下:

  1. 删除顶级列表中的第n个元素
  2. 从#1
  3. 的结果中递归删除每个子列表中的第n个元素

    我这样实现它:

    (defun (del n l)
      (defun (del-top-level n l)
        ...) ; return l but with nth gone
      (mapcar #'(lambda (l) (if (not (listp l)) l (del n l)))
              (del-top-level n l)))
    

    您需要实施del-top-level功能。

答案 2 :(得分:-1)

好的我想我知道你需要什么。

您应该需要两个功能

entry函数只调用一个辅助函数,如(DeleteHelper position position myList)

如果当前位置不为0,DeleteHelper将递归调用自身并可选地包含列表的当前元素。例如(cons(car myList)(DeleteHelper( - position 1)originalPosition(cdr myList))

如果DeleteHelper遇到列表,则递归遍历列表,并将位置重置为原始传入位置。如(缺点(DeleteHelper originalPosition originalPosition(car myList))(DeleteHelper( - position 1)originalPosition(cdr myList)))

还要记住基本情况(我想在遍历整个列表后返回一个空列表)。

这应该让你朝着正确的方向前进。我编写任何Lisp已经有几年了,所以我的语法可能有点过时了。