2012-03-07 88 views
5

如果您曾經玩過Minecraft,以下將會更有意義。由於你們許多人都沒有,我會盡力盡我所能解釋它Python遞歸數據讀取

我想寫一個遞歸函數,可以找到從minecraft的食譜平面文件製作任何我的世界物品的步驟。這一個讓我真的很難過。

Flatfile有點長,所以我把它包含在this的要點中。

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} 

所以問題是,我該怎麼做呢?

我知道要求人們爲你做的工作在這裏皺起了眉頭,所以如果你覺得這與你有點太接近,只是爲我編碼,就這麼說吧。

+2

只是說,但我覺得你的樣本輸出是不正確的...... – PearsonArtPhoto 2012-03-07 00:13:36

+0

以何種方式是不正確的? – giodamelio 2012-03-07 00:15:44

+2

那麼,insulated_copper_cable不是一個基礎項目,是嗎? electronic_circuit也不是。看來你想要的基礎成分,而不是複雜的。 – PearsonArtPhoto 2012-03-07 00:20:09

回答

3

這可以使用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} 
1

我認爲問題是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 

編輯:評論填補了我缺乏的蟒蛇知識,所以這裏有一個更好的解決方案。

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 
+0

他希望的輸出是一個字典,所以,而不是chain.append,你應該做* chain.setdefault(item,0)+ = quantity * – 2012-03-07 00:23:36

+0

@campos:這不會按預期工作,值不會增加。 'defaultdict(int)'在這裏是理想的數據結構。 – 2012-03-07 00:24:19

+0

哎呀,這是真的。 – 2012-03-07 00:27:13