我正在使用以下代码迭代字典列表以找到相应的键['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])
答案 0 :(得分:3)
快速检查还会显示4 in dictA
比4 in dictA.keys()
更快。
答案 1 :(得分: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的Zen有关。你很熟悉Python程序的外观,因为很明显你似乎在尝试用Python编写类似C / Java的代码。
答案 2 :(得分: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]的值是可散列的并且具有与equals一致的散列 - 大多数内置类都是,但是一些自定义类可能无法正确实现散列。
答案 3 :(得分:1)
Oneliner:
%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
答案 4 :(得分: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]
]
答案 5 :(得分:0)
你应该总是测试速度,但是生成器表达式(或列表推导)应该比迭代更快:
result= []
A = (a for a in listA if 5 in a)
for a in A:
result.extend(b[5] for b in listB if (5 in b and a[5] == b[5]))
或尝试去实现:
import functools
fives = partial(filter, lambda x: 5 in x)
for a in fives(listA):
result.extend(b[5] for fives(listB) if a[5] == b[5])