简体   繁体   English

Python 中的递归,从每个循环创建几个新实例

[英]Recursion in Python, creating several new instances from each loop

I have a problem where I have a dictionary that contains class objects, that references one or more items.我有一个问题,我有一个包含类对象的字典,它引用了一个或多个项目。 The key of the dictionary is the id of each item.字典的键是每个项目的 id。 I am trying to set up a recursive function for finding the chain of adjacent item IDs, for x steps.我正在尝试为 x 步设置一个递归函数来查找相邻项目 ID 链。

It works, but only if there is only one item in each "adjacent_items"-variable.它有效,但前提是每个“adjacent_items”变量中只有一个项目。 If there are more, it still only catches the first and moves on.如果还有更多,它仍然只捕获第一个并继续前进。 In the example the "7" is never handled.在示例中,从未处理过“7”。

I am very new to recursive functions, but I feel like there should be an efficient way so solve this with recursion.我对递归函数很陌生,但我觉得应该有一种有效的方法,所以用递归来解决这个问题。 Any input would be appreciated.任何输入将不胜感激。

class Item:
    def __init__(self, id_num: str, adjacent: list):
        self.id = id_num
        self.adjacent_items = adjacent


def get_adjacent_x_steps(start: str, item_dict: dict, x: int, wip_set=None):
    """Get adjacent items for x steps"""

    if wip_set is None:
        wip_set = set()
    if x != 0:
        x -= 1
        for item in item_dict[start].adjacent_items:
            wip_set.add(item)
            # Todo, only takes first hit, return exits this instance..
            return get_adjacent_x_steps(item, item_dict, x, wip_set)
    else:
        return wip_set


def example():
    """Example items"""
    item1 = Item("1", ["4", "7"])
    item2 = Item("4", ["5"])
    item3 = Item("7", ["5"])
    item4 = Item("5", ["8", "17"])

    item_dict = {}
    for item in (item1, item2, item3, item4):
        item_dict[item.id] = item

    chained_items = get_adjacent_x_steps("1", item_dict, 2)

    print(chained_items)


if __name__ == '__main__':
    example()

I am not sure whether you want to get the paths along with x steps, or only the destinations.我不确定您是要获取路径和x步,还是只获取目的地。 If the latter is the case, try the following:如果是后者,请尝试以下操作:

class Item:
    def __init__(self, id_num: str, adjacent: list):
        self.id = id_num
        self.adjacent_items = adjacent

def get_adjacent_x_steps(start, item_dict, x):
    if x == 0 or start not in item_dict:
        return [[]]
    return [[adj, *lst]
            for adj in item_dict[start].adjacent_items
            for lst in get_adjacent_x_steps(adj, item_dict, x - 1)]

item1 = Item("1", ["4", "7"])
item2 = Item("4", ["5"])
item3 = Item("7", ["5"])
item4 = Item("5", ["8", "17"])
item_dict = {i.id: i for i in (item1, item2, item3, item4)}

print(get_adjacent_x_steps('1', item_dict, 1))
print(get_adjacent_x_steps('1', item_dict, 2))
print(get_adjacent_x_steps('1', item_dict, 3))

Recursion happens at the list comprehension;递归发生在列表理解中; at start , get all adjacent items ( for adj in item_dict[start].adjacent_items ), and apply the function to those items with one step less ( get_adjacent_x_steps(adj, item_dict, x - 1) ).start ,获取所有相邻项目( for adj in item_dict[start].adjacent_items ),并将该函数应用于那些少一步的项目( get_adjacent_x_steps(adj, item_dict, x - 1) )。 Then return the resulting list lst along with adj .然后返回结果列表lstadj

Output:输出:

[['4'], ['7']]
[['4', '5'], ['7', '5']]
[['4', '5', '8'], ['4', '5', '17'], ['7', '5', '8'], ['7', '5', '17']]

If you want to get the set of destinations, then you can apply set comprehension afterwards:如果你想得到一组目的地,那么你可以在之后应用集合理解:

print({x[-1] for x in get_adjacent_x_steps('1', item_dict, 3)})
# {'17', '8'}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM