Python:如何遍历 List[Dict{List[Dict{}]}]?

3

我在想是否有一种简单的方法来实现这个。我有一个从文件解析出来的特定结构,输出是一个列表,里面包含字典和列表。目前,我只有一点代码,大致如下:

for i in xrange(len(data)):
    for j, k in data[i].iteritems():
        for l in xrange(len(data[i]['data'])):
            for m, n in data[i]['data'][l].iteritems():
                dostuff()

我想知道是否有一种函数可以遍历一个结构并在内部确定每个条目是列表还是字典,如果是字典,则遍历该字典等等。 我只使用Python大约一个月左右,所以我绝不是这种语言的专家甚至是中级用户。 预先感谢您的答案。
编辑:即使可以简化我的代码,也会有所帮助。

3
没有,系统内没有这种功能。 - martineau
4个回答

10

永远不需要通过xrange(len(data))来迭代。对于列表,你应该通过迭代data,而对于字典,你应该通过迭代data.items()(或values())。

你的代码应该像这样:

for elem in data:
    for val in elem.itervalues():
        for item in val['data']:

这个要短得多。


1
补充一点:如果你想要一个值的索引和这个值本身,你可以这样写 for (i,elem) in enumerate(data): - kqr
谢谢,我知道一定有更简单的方法,只是找不到。 - Josh
好的,现在我有另一个问题。在我的示例代码中,假设我想访问:如果data[i][more_data] == 'a_dict'。当我尝试执行data[elem][more_data]时,我当然会收到错误:列表索引必须是int而不是dict。我认为这就是我按照自己的方式进行操作的原因,因为我无法弄清楚如何访问每个单独的元素并检查它。 - Josh
1
for elem in data 处理元素访问,背后为您处理。它基本上就像执行 for i in xrange(len(data)): elem = data[i]。因此,您遇到问题的代码行应该是 elem[more_data] 而不是 data[i][more_data] - Benjamin Hodgson
哇,我真是个笨蛋。我刚刚才意识到我一直可以像 i['more_data'] 这样做某些事情。谢谢 @poorsod - Josh

5

如果你想要遍历一个任意的数组/哈希结构,那么你可以创建一个基于type()函数的函数来实现。

def traverse_it(it):
    if (isinstance(it, list)):
        for item in it:
            traverse_it(item)
    elif (isinstance(it, dict)):
        for key in it.keys():
            traverse_it(it[key])
    else:
        do_something_with_real_value(it)

请注意,一般的面向对象专家会告诉你不要这样做,而是创建一个类树,其中一个基于数组,另一个基于字典,然后使用相同的函数名称(即虚拟函数)来处理每个类,并在每个类函数内调用它。也就是说,基于类型的if/else树是“不好”的。可以在对象上调用的函数以其自己的方式处理其内容是“好”的。

isinstance(it, list)isinstance(it, dict)type(it) == type([]) 更好。 它更易读,并且在列表和字典的子类上也可以工作。当然,如果需要“鸭子类型”,这种方法根本行不通,必须用 try...except 风格来替代。 - Benjamin Hodgson

1
我认为这就是你想做的。不需要使用xrange()从列表中提取索引,因为for循环遍历列表的每个值。在下面的示例中,d1是对当前data[i]的引用。
for d1 in data: # iterate over outer list, d1 is a dictionary
    for x in d1: # iterate over keys in d1 (the x var is unused)
        for d2 in d1['data']: # iterate over the list

            # iterate over (key,value) pairs in inner most dict
            for k,v in d2.iteritems():
                dostuff()

你还两次使用了名称l(有意或无意),但要注意作用域的工作方式。


是的,应该是m和n。 - Josh

0

嗯,这个问题很老了。然而,出于我的好奇心,我想回答你的问题,以得到更好的答案,我刚刚尝试了一下。

假设字典如下:dict1 = {'a':5,'b':[1,2,{'a':100,'b':100}],'dict 2':{'a':3,'b':5}}

解决方案: dict1 = {'a':5,'b':[1,2,{'a':100,'b':100}],'dict 2':{'a':3,'b':5}} def recurse(dict): if type(dict) == type({}): for key in dict: recurse(dict[key]) elif type(dict) == type([]): for element in dict: if type(element) == type({}): recurse(element) else: print element else: print dict recurse(dict1)


我建议不要使用dict和list作为变量名。 - Pithikos
字典和列表不像名称一样使用,这些集合在此处被用作对象。 - shashankS
你正在使用 dict 作为变量名。这可能是有效的,但对于阅读你代码的其他人来说可能会造成困惑。 - Pithikos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接