Python:如何快速迭代字典列表

2 投票
6 回答
1713 浏览
提问于 2025-04-18 00:34

我正在使用以下代码来遍历字典列表,寻找一个对应的键 ['5'],并在找到后比较它的值。虽然这个方法可以正常工作,但我觉得可以改进一下,以提高性能。还有哪些其他方法可以实现同样的结果呢?

listA = [{1:'One', 2:'Two', 3:'Three'}, {4:'Four', 5:'Five', 6:'Six'}]
listB = [{4:'Four', 5:'Five', 6:'Six'}, {7:'Seven', 8:'Eight', 9:'Nine'}]

result=[]
for dictA in listA:
    if not 5 in dictA.keys(): continue
    for dictB in listB:
        if 5 in dictB.keys() and dictB[5]==dictA[5]:
            result.append(dictB[5])

6 个回答

0
result = [
    y[5]
    for x in listA
    if 5 in x
    for y in listB
    if 5 in y and x[5] == y[5]
]

这段代码是用来处理某些数据的。它可能涉及到一些循环和条件判断,帮助程序根据不同的情况做出不同的反应。具体来说,代码块中的每一行都有它的作用,可能是获取数据、处理数据或者输出结果。

如果你是编程新手,可以把这段代码想象成一个简单的食谱。每一步都很重要,缺少了哪一步,最终的结果可能就不对了。理解每一行代码的意思,就像理解食谱中的每一个步骤,才能做出美味的菜肴。

总之,这段代码的目的是为了让程序能够智能地处理信息,做出相应的决策。希望你能慢慢理解这些代码是如何工作的!

1

一行代码:

%timeit filter(None, {item.get(5) for item in listA}.intersection(item.get(5) for item in listB))
100000 loops, best of 3: 8.59 us per loop

%%timeit
    ...: listA = [{1:'One', 2:'Two', 3:'Three'}, {4:'Four', 5:'Five', 6:'Six'}]
    ...: listB = [{4:'Four', 5:'Five', 6:'Six'}, {7:'Seven', 8:'Eight', 9:'Nine'}]
    ...: 
    ...: result=[]
    ...: for dictA in listA:
    ...:     if not 4 in dictA.keys(): continue
    ...:     for dictB in listB:
    ...:         if 5 in dictB.keys() and dictB[5]==dictA[5]:
    ...:             result.append(dictB[5])
    ...:             
100000 loops, best of 3: 11.9 us per loop
2

你需要对代码进行性能分析,看看是否有改进。不过,通常来说,使用内置的过滤功能比自己写过滤代码要好,因为这样可以省去解释你那些过滤代码的时间。

for dictA in filter(lambda x : 4 in x, listA):
    for dictB in filter(lambda x : 5 in x, listB):
        if dictB[5]==dictA[5]:
            result.append(dictB[5])

而且,这样的代码会更简短,也更容易阅读,这符合Python的设计理念。你应该熟悉一下Python程序的样子,因为你看起来是在尝试用C或Java的风格来写Python代码。

3

快速检查一下可以发现,4 in dictA4 in dictA.keys() 要快。

2

首先,你并不需要用到大部分的 listA,你关心的只是 dictA[5] 里的值。所以我们只提取你关心的部分,放在一个能快速访问的数据结构里:

interesting_vals = frozenset([dictA[5] for dictA in listA if 5 in dictA])

接下来,我们需要检查 listB。有两种方法。先说说比较明显的那种:

result = [dictB[5] for dictB in listB
          if 5 in dictB and dictB[5] in interesting_vals]

或者,如果你预计大多数的 dictB 都会有一个 [5] 的元素,那么这种方法可能会更快,因为它把访问和存在性检查结合在了一起(用真实数据来测试一下效果!):

NA = object()  # Will compare different to everything in interesting_vals
result = [dictB[5] for dictB in listB if dictB.get(5, NA) in interesting_vals]

这个解决方案的时间复杂度应该是 O(len(listA) + len(listB)),这比你原来的 O(len(listA) * len(listB)) 要好很多,特别是当列表很大的时候。

需要注意的是,我假设 dictA[5] 的值是可以哈希的,并且哈希值和相等性是一致的——大多数内置类都是这样的,但有些自定义类可能没有正确实现哈希。

撰写回答