【发布时间】:2015-02-10 02:58:11
【问题描述】:
我正在尝试编写代码,该代码将采用一个可以包含任意大量嵌套对象的对象,每个嵌套对象都可以包含嵌套对象,依此类推。我正在尝试编写一个函数来查找与给定条件匹配的 first 对象。我不在乎匹配所有对象。
Python 2 是这里的语言,但这个理论应该适用于任何语言。
class MyObject:
myType = ""
myChildren = list([])
def __init__(self, t):
self.myType = t
a = MyObject("top")
a.myChildren.append(MyObject("obj1"))
a.myChildren.append(MyObject("obj2"))
a.myChildren.append(MyObject("obj3"))
a.myChildren[1].myChildren.append(MyObject("objA"))
a.myChildren[1].myChildren.append(MyObject("objB"))
a.myChildren[1].myChildren.append(MyObject("objC"))
a.myChildren[1].myChildren[0].myChildren.append(MyObject("Sam"))
a.myChildren[1].myChildren[0].myChildren.append(MyObject("Max"))
a.myChildren[1].myChildren[0].myChildren.append(MyObject("Waldo"))
a.myChildren[1].myChildren[1].myChildren.append(MyObject("Adam"))
a.myChildren[1].myChildren[1].myChildren.append(MyObject("Waldo"))
a.myChildren[2].append("Waldo"))
此时我们应该有一个看起来像这样的递归树:
[top]
|-- [obj1]
|-- [obj2]
| |-- [objA]
| | |-- [Sam]
| | |-- [Max]
| | \-- [Waldo]
| |-- [objB]
| | |-- [Adam]
| | \-- [Waldo]
| \-- [objC]
\-- [obj3]
\-- [Waldo]
所以现在,我想编写一个函数来查找并返回对 Waldo 的 first 实例的引用。如您所见,Waldo 可能不止一个。我只对top/obj2/objA/Waldo 实例感兴趣。
我过去做过的唯一递归代码使用递归返回来逐步返回更多内容。例如:将创建递归树的函数:
def printTree(rootObj,indentLevel=0):
output = "%s%s\n" % (" "*indentLevel, rootObj.myType)
for obj in rootObj:
output += printTree(obj,indentLevel+1)
return output
问题是,正如我所说,我只想要 第一个 实例,并且我想在那个时候停止遍历树。一旦树变大并且所需的对象位于树的早期某处,遍历整棵树的效率将非常低。
我似乎无法弄清楚实现这一点的逻辑是如何运作的。我最初的想法是这样的:
def findFirst(rootObj, desiredType):
# test this object first
if (rootObj.myType == desiredType):
return rootObj
# we are not the correct object, so now test all sub-objects.
for (obj in rootObj):
if (findFirst(obj,desiredType) is not None):
return obj
return None # nothing was found
然而这并不完全奏效。因为它只是返回第一个对象,即使它不匹配。
有人可以帮助阐明完成此操作所需的逻辑吗?
编辑:一些澄清。递归的方法是我们将尽可能深入到树中,然后为每个对象返回。该列表也是有序的。因此,例如,上述树的递归路径将是:
top -> obj1 -> obj2 -> objA -> Sam -> Max -> Waldo -> objB -> Adam -> Waldo -> objC -> obj3 -> Waldo
另外,我确实给出了一个自创建对象的示例,但是,我想在其中使用此代码的应用程序中的对象是动态创建的;因此,序列化或转换对象树最终会遍历整个树,这会减慢速度,因为我们是根据状态生成动态对象。
查看我要查找的内容的一个好方法是递归文件搜索功能。假设我们在磁盘上有一个文件夹,我们希望该文件夹中的第一个文件 anywhere 根据正则表达式匹配给定的文件名并且具有给定条件内的大小。 (这意味着我们必须对每个对象进行计算,我们不能简单地检查变量并根据它们进行过滤。)但是,如果该文件位于根目录中,我们不想解析整个驱动器的目录结构或在我们来到的第一个目录中。我的问题的真正精神是“一旦找到符合您所需条件的东西,您如何才能摆脱这个递归循环?”
【问题讨论】:
-
那么您希望第一次出现关于子索引值的情况吗?我认为第一次出现的是 waldo,它落在树深处 2 层,而不是位于第 3 层的 waldo(但附加在索引 1)
-
不,我们在走树的时候,先走最深的方法遇到的第一个物体。换句话说,我不想检查深度 1 的 all,然后检查深度 2 的所有,依此类推。相反,我想检查深度 1 对象,但是当遇到另一个层时,first 下降到该层,然后再进入下一个级别 1 对象。
标签: recursion python-2.x