2012-08-01 28 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