2012-08-01 69 views
0

我正在研究將多級字典轉換爲單級詞典列表的功能。Python pop()不會刪除項目

邏輯似乎是正確的。但是當我運行它時,while循環運行無窮大。我發現它第一次進入while循環,next_level.pop()正在工作。從while循環的第二次開始,pop()函數不會刪除最後一項next_level。我還嘗試通過next_level[-1]檢索最後一個項目,並刪除最後一個項目del next_level[-1]。但結果是一樣的。我認爲這可能與參考文獻有關。任何想法?

def flat_dict(self, params): 
    """convert a multi-level dictionary to a list of one-level dictionaries""" 
    plist = next_level = [] 
    next_level.append(params) 
    while next_level: 
     current_level = temp_level = next_level.pop() 
     for k, v in current_level.iteritems(): 
      if isinstance(v, dict): 
       next_level.append(temp_level.pop(k)) 
       pk = [x for x in next_level[-1].keys() if x.endswith('_id')] 
       temp_level[pk[0]] = next_level[-1][pk[0]] 
     plist.append(temp_level) 
    return plist 
+0

'pop()'函數似乎對我可靠地工作。你能解釋一下「我認爲它可能與參考事物有關」嗎? – 2012-08-01 20:57:18

+0

你能解釋一下你想做什麼嗎?我發現你的代碼難以遵循,所以我想要更多的解釋。 – steveha 2012-08-01 21:06:06

+0

@GregHewgill因爲當對象是可變的時候python是通過引用傳遞的。所以我猜想它可能是相關的。 – Conan 2012-08-01 21:06:09

回答

1

沒有字典的一個例子,它有點難以想像......但一般來說,像這樣的情況下,我建議遞歸反正:

def flatten(data): 
    output = [] 
    if (isinstance(data, dict)): 
     output.append(data) 
     for value in data.values(): 
      output += flatten(value) 
    return output 

在直接回答你問題,我不是100%確定發生了什麼問題 - 我可以說pop()本身就能正常工作。我猜這跟你初始化plist的方式有關,你會得到一個無限循環嗎?

plist = next_level = [] 

此行實際上是設置的plist和next_level到完全相同列表 - 不進行初始化每個變量列表爲空。

>>> plist = next_level = [] 
>>> plist.append(1) 
>>> next_level 
[1] 

當你修改的plist,後來在你的循環,你實際上是修改next_level也未何意是我的猜想...嘗試定義你的plist/next_level這樣:

plist = [] 
next_level = [] 

然後看看會發生什麼。

+0

是的,鏈分配會導致這個問題。我不應該爲init可變變量使用鏈分配。謝謝! – Conan 2012-08-01 22:34:35

0

我不完全明白你想要做什麼,所以我不認爲這個答案將正是你所需要的。但也許你可以用它作爲解決方案的開始。

這個答案不會改變dict被壓平;它只是遍歷它並構建一個新的dict實例的列表。它自己調用遞歸來壓扁任意嵌套的dict

def flat_dict(self, d_to_flatten, lst_flat=None): 
    """convert a multi-level dictionary to a list of one-level dictionaries""" 
    if lst_flat is None: 
     lst_flat = [] 

    d = {} 
    lst = [] 
    for k, v in d_to_flatten.iteritems(): 
     if isinstance(v, dict): 
      lst.append(v) 
     else: 
      d[k] = v 
    lst_flat.append(d) 
    for d in lst: 
     flat_dict(self, d, lst_flat) 

    return lst_flat