Python:如何快速迭代字典列表
我正在使用以下代码来遍历字典列表,寻找一个对应的键 ['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 个回答
result = [
y[5]
for x in listA
if 5 in x
for y in listB
if 5 in y and x[5] == y[5]
]
这段代码是用来处理某些数据的。它可能涉及到一些循环和条件判断,帮助程序根据不同的情况做出不同的反应。具体来说,代码块中的每一行都有它的作用,可能是获取数据、处理数据或者输出结果。
如果你是编程新手,可以把这段代码想象成一个简单的食谱。每一步都很重要,缺少了哪一步,最终的结果可能就不对了。理解每一行代码的意思,就像理解食谱中的每一个步骤,才能做出美味的菜肴。
总之,这段代码的目的是为了让程序能够智能地处理信息,做出相应的决策。希望你能慢慢理解这些代码是如何工作的!
一行代码:
%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
你需要对代码进行性能分析,看看是否有改进。不过,通常来说,使用内置的过滤功能比自己写过滤代码要好,因为这样可以省去解释你那些过滤代码的时间。
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代码。
快速检查一下可以发现,4 in dictA
比 4 in dictA.keys()
要快。
首先,你并不需要用到大部分的 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]
的值是可以哈希的,并且哈希值和相等性是一致的——大多数内置类都是这样的,但有些自定义类可能没有正确实现哈希。