在数据模型中任意深度的所有对象的递归列表?

时间:2018-04-26 19:19:37

标签: python python-3.x recursion

假设我有一个由Python中的对象组成的数据结构,如下所示:

class Planet:
    def __init__(self, name):
        self.name = name
        self.continents = []

class Continent:
    def __init__(self, name):
        self.name = name
        self.countries = []

class Country:
    def __init__(self, name):
        self.name = name
        self.states = []

class State:
    def __init__(self, name):
        self.name = name
        self.cities = []

class City:
    def __init__(self, name):
        self.name = name

现在假设我要创建一个能够将对象和属性“path”作为参数的函数,并输出“匹配”该路径的所有对象的列表。因为我真的不知道如何很好地描述我在想什么,而且很可能我使用了错误的术语,这里有一个关于它在实践中可能是什么样子的想法(让我们调用函数{{1} },并假设数据结构填充了数据,collect是数据结构的“根”对象):

planet

此函数调用将返回地球上每个洲的每个国家/地区中每个州的每个城市的列表。或者,如果我想要数据模型中的所有状态,我会这样做:

planet = Planet("Earth")
... Code for populating data structure ...

collect(planet, "continents.countries.states.cities")

希望你明白了。问题是我不知道如何实现这一目标。这是我到目前为止所提出的:

collect(planet, "continents.countries.states")

有谁知道如何才能使这项工作?

1 个答案:

答案 0 :(得分:0)

如果您想进行广度优先搜索:

def bfs(queue, results):
    try:
        obj, attr_path = queue.pop(0)
    except IndexError:
        return

    if attr_path is None:
        results.append(obj)
    else:
        if '.' in attr_path:
            first, rest = attr_path.split('.', maxsplit=1)
        else:
            first, rest = attr_path, None

        children = getattr(obj, first)
        for child in children:
            queue.append((child, rest))

    bfs(queue, results)

def collect(obj, attr_path):
    queue = [(obj, attr_path)]
    results = []
    bfs(queue, results)
    return results

免责声明:未经测试