【问题标题】:Python Recursive Data ReadingPython 递归数据读取
【发布时间】:2012-03-07 08:48:33
【问题描述】:

如果你曾经玩过我的世界,以下内容会更有意义。由于你们中的许多人都没有,我会尽力解释它

我正在尝试编写一个递归函数,它可以找到从我的世界食谱平面文件中制作任何我的世界物品的步骤。这个真的让我难过。

平面文件有点长,所以我将它包含在this gist 中。

def getRecipeChain(item, quantity=1):
    #magic recursive stuffs go here

所以基本上我需要查找第一个配方,然后查找第一个配方的所有组件的配方,依此类推,直到找到没有配方的项目。每次我需要将配方附加到一个列表中,这样我就会得到一个关于制作物品顺序的指令集。

所以这是我现在拥有的功能(那个不起作用)

def getRecipeChain(name, quantity=1):
    chain = []

    def getRecipe(name1, quantity1=1):
        if name1 in recipes:
            for item in recipes[name1]["ingredients"]["input"]:
                if item in recipes:
                    getRecipe(item, quantity1)
                else:
                    chain.append(item)

    getRecipe(name, quantity)
    return chain

这是我想要的理想输出。它是一个字典,其中存储了项目名称和数量。

>>> getRecipeChain("solar_panel", 1):
{"insulated_copper_cable":13, "electronic_circuit":2, "re_battery":1, "furnace":1, "machine":1, "generator":1, "solar_panel":1}

那么问题来了,我该怎么做呢?

我知道在这里要求人们为你工作是不受欢迎的,所以如果你觉得这有点过于接近你只是为我做编码,那就这么说吧。

【问题讨论】:

  • 只是说,但我认为您的示例输出不正确...
  • 好吧,insulated_copper_cable 不是基础项目,是吗?电子电路也不是。看来您想获得基本成分,而不是复杂成分。
  • Shameless plug - 非常感谢您的意见。这几乎正​​是我想要的想法。

标签: python recursion minecraft


【解决方案1】:

这可以使用支持加法的collections.Counter 优雅地解决:

from collections import Counter

def getRecipe(name, quantity=1):
  if not name in recipes: return Counter({name: quantity})

  subitems = recipes[name]["ingredients"]["input"]
  return sum((getRecipe(item, quantity) for item in subitems), 
             Counter())

print repr(dict(getRecipe("solar_panel")))
# => {'copper': 39, 'refined_iron': 10, 'glass': 3, 
#     'rubber': 78, 'cobblestone': 8, 'tin': 4, 
#     'coal_dust': 3, 'nothing': 10, 'redstone': 6}

【讨论】:

    【解决方案2】:

    我认为问题是 2 倍。首先,您需要在对 getRecipe() 的递归调用中将项目附加到链中。其次,我认为这两个功能不必要地使事情复杂化。我认为只有内在的应该做。像这样的东西就是你要找的东西。我还没有测试过它,但它应该足够接近让你开始走上正轨。

    def getRecipe(name, quantity=1):
        chain=[];
        if name in recipes:
            for item in recipes[name]["ingredients"]["input"]:
                if item in recipes:
                    chain.append(getRecipe(item, quantity))
                else:
                    chain.append(item)
        return chain
    

    编辑:cmets 填补了我对 python 知识的不足,所以这里有一个更好的解决方案。

    from collections import Counter
    def getRecipe(name, quantity=1, count=Counter()):
        if name in recipes:
            for item in recipes[name]["ingredients"]["input"]:
                if item in recipes:
                    getRecipe(item, quantity,counter)
                else:
                    counter[item]+=quantity
        return counter
    

    【讨论】:

    • 他想要的输出是一个字典,所以你应该用 chain.setdefault(item, 0) += quantity 代替 chain.append
    • @campos:这不会按预期工作,值不会增加。 defaultdict(int) 将是这里理想的数据结构。
    • 我已经更新了我的解决方案,感谢您在 Python 上填补我的空白;-)
    • @giodamelio:如果你给它一个基本项作为参数它不起作用:getRecipe("copper", 1),这有点不一致。
    • @NiklasB。是的,我不知道如何解决这个问题。不过我不认为这会是个问题。
    猜你喜欢
    • 2011-01-13
    • 1970-01-01
    • 2014-10-27
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    相关资源
    最近更新 更多