-2

似乎有很多与嵌套 for 循环的速度有关的问题和答案——我想我看了每一个!但不幸的是,我仍然不确定为什么我的代码很慢。希望能得到各位好心人的指导。

我每天下载一个包含约 116,000 个条目的 csv 文件。项目在文件中不一致的点被添加和删除,所以每天我都想看看添加了什么,删除了什么。

对于旧列表和新列表,将条目从 csv 获取到列表完全不需要时间,但是我在代码的下一部分遇到了很大的速度下降,尽管最后,它做了我想要的并吐出区别 - 添加的项目和删除的项目。

列表中的 116,000 个项目中的每一个都是一个字典,如下所示:

old or new = [{'Date Stamped': '', 'Name': '', 'Registration Number': '', 'Type': '', "Form Name':  '', 'URL': "}]

当我到达这一点时:

added = [i for i in new if not i in old]
removed = [i for i in old if not i in new]

完成需要25分钟!我觉得这很长一段时间,但我可能并不完全理解我在做什么。

每个列表(旧的和新的)都有约 116000 个项目。那是因为我必须迭代约 116,000 个项目 4 次吗?

最后,它做了我想做的事,但它的工作似乎非常缓慢;也就是说,这真的是我第一次使用包含这么多项目的数据集,所以也许这是理所当然的。

因为它是嵌套的 for 循环,所以这很慢吗?是因为尺寸慢吗?我绝对是一个业余爱好者,非常感谢大家的帮助。非常感谢。

4

1 回答 1

2

实际上,的,它很慢,因为它是一个嵌套的 for 循环,因为它的大小。

Python 的element in list操作是通过逐个元素搜索整个列表来找到它想要的。如果您必须newold.new

列表不是一个很好的搜索数据结构。相反,如果您有这样的用例,您应该做的是将它们转换为set第一个 - 一个无序集合(但顺序可能无关紧要),它使用哈希表来确定其中是否存在元素。现在,不是逐个元素地搜索整个数据结构,它可以只是散列正在搜索的元素,检查那里是否有一个元素,如果有,就说出来。

换句话说,element in set比 效率高一个数量级element in list。对于相对较小的开销成本(set首先创建 s),这可以节省大量for循环时间:

old_set = set(old)
new_set = set(new)
added = [i for i in new if not i in old_set]
removed = [i for i in old if not i in new]

此外,您甚至可以省去列表推导,因为它set支持集合论中的操作 - 获取两个集合之间的差异(一个集合中的元素不在另一个集合中)就像减去它们一样简单:

added = list(new_set - old_set)  # (new_set - old_set) is identical to new_set.difference(old_set)
removed = list(old_set - new_set)

这可能比列表推导更有效,因为它针对这个用例进行了优化。

于 2020-09-01T17:37:14.023 回答