通过列表推导或任何其他方法解决嵌套的dict迭代

时间:2014-05-29 09:41:38

标签: python dictionary dictionary-comprehension

我的dict中包含另一个dict

d1 = {'a':{'p':1, 'q':2, 'r':'abc'}, 
      'b':{'p':5, 'q':6, 'r':["google", "pypi.org"]}
     }
url1 = "https://google.com"
url2 = "https://abc.com"

现在我要做的是检查来自r的{​​{1}}值,但我不希望任何代码冗余。如何可能?

我现在正在做的是: -

dict values

现在问题出现了同样的for k, v in d1.iteritems(): if isinstance(v['r'], list): for l in v['r']: if url1.find(l): ..Do something.. else: continue else: if url1.find(v['r'): ..Do Something same as above.. else: continue 重复2次,有没有办法用理解或任何其他方法解决冗余,除了函数制作和调用< / strong>。

编辑 - 代码已经在一个大的函数定义中,所以提供其他解决方案,而不是创建另一个函数并调用它。

3 个答案:

答案 0 :(得分:2)

您可以转换非列表项,即。在这种情况下,将字符串转换为列表,然后简单地遍历该列表。而且您不需要else: continue部分:

for k, v in d1.iteritems():
    value = v['r'] if isinstance(v['r'], list) else [v['r']]
    for l in value:
        if url1.find(l):
           #Do something..

答案 1 :(得分:2)

如果您对python代码中的性能非常认真,并且愿意接受某些风格上的妥协,则以下表单的运行速度与手动内联代码一样快,假设您使用pypy

def inner():
    pass

for k, v in d1.items():
    if isinstance(v['r'], list):
        for l in v['r']:
            if url1.find(l):
                inner()
            else:
                continue
    else:
        if url1.find(v['r']):
            inner()
        else:
            continue

有关更为现实的示例,包括非空内部和一些时序代码,请参阅this link.

请注意,就像你写的那样,这个版本明显慢于CPython下的内联版本,当然它没有JIT内联。

答案 2 :(得分:1)

奇特是对的。使用函数将是这里的最佳解决方案。使用函数调用的开销可以忽略不计,它可能比创建新列表和循环遍历长度为1的列表要少。

但是,如果您确实希望不惜一切代价避免代码重复并避免多个函数调用,则可能需要考虑将代码重写为生成器函数。这将产生您想要一次处理一个的项目。

def loop(d1):
    for k, v in d1.iteritems():
        if isinstance(v['r'], list):
            for l in v['r']:
                if url1.find(l):
                    yield l
                else:
                    continue
        else:
            if url1.find(v['r']):
                yield v['r']
            else:
                continue

for item in loop(d1):
    print "do something"