Python 中巨大增长列表的高效逆序比较
Efficient reverse order comparison of huge growing list in Python
在 Python 中,我的目标是维护一个唯一的点列表(复杂标量,四舍五入),同时稳定地创建具有函数的新点列表,就像在这个伪代码中一样
list_of_points = []
while True
# generate new point according to some rule
z = generate()
# check whether this point is already there
if z not in list_of_points:
list_of_points.append(z)
if some_condition:
break
现在 list_of_points
在此过程中可能会变得非常庞大(例如 1000 万个条目甚至更多),并且重复项非常频繁。事实上,大约 50% 的时间,新创建的点已经在列表中的某处。然而,我所知道的是,通常已经存在的点 接近列表的末尾 。有时它在“批量”中,只是偶尔会在开头附近找到。
这让我想到了以相反的顺序进行搜索。但是,考虑到我可能会在这个过程中增长的庞大列表,我将如何最有效地做到这一点(就原始速度而言)。 list
容器在这里是最好的方法吗?
通过这样做我设法获得了一些性能
list_of_points = []
while True
# generate new point according to some rule
z = generate()
# check very end of list
if z in list_of_points[-10:]:
continue
# check deeper into the list
if z in list_of_points[-100:-10]:
continue
# check the rest
if z not in list_of_points[:-100]:
list_of_points.append(z)
if some_condition:
break
显然,这不是很优雅。使用第二个 FIFO 型容器 (collection.deque),可以提供大致相同的加速。
你最好的选择可能是使用集合而不是列表,python 集合使用散列来插入项目,所以速度非常快。而且,您可以跳过检查项目是否已在列表中的步骤,只需尝试添加它即可,如果它已经在集合中,则不会添加,因为不允许重复。
窃取你的伪代码示例
set_of_points = {}
while True
# get size of set
a = len(set_of_points)
# generate new point according to some rule
z = generate()
# try to add z to the set
set_of_points.add(z)
b = len(set_of_points)
# if a == b it was not added, thus already existed in the set
if some_condition:
break
使用 set
。这就是集合的用途。啊 - 你已经有了答案。所以我的其他评论:您的这部分代码似乎不正确:
# check the rest
if z not in list_of_points[100:]:
list_of_points.append(z)
在上下文中,我相信你打算在那里写 list_of_points[:-100]
。您已经检查了最后 100 个,但是,您现在跳过检查 first 100 个。
但更好的是,使用普通 list_of_points
。随着列表变长,与复制 len(list_of_points) - 100
个元素
的成本相比,可能进行 100 次冗余比较的成本变得微不足道
在 Python 中,我的目标是维护一个唯一的点列表(复杂标量,四舍五入),同时稳定地创建具有函数的新点列表,就像在这个伪代码中一样
list_of_points = []
while True
# generate new point according to some rule
z = generate()
# check whether this point is already there
if z not in list_of_points:
list_of_points.append(z)
if some_condition:
break
现在 list_of_points
在此过程中可能会变得非常庞大(例如 1000 万个条目甚至更多),并且重复项非常频繁。事实上,大约 50% 的时间,新创建的点已经在列表中的某处。然而,我所知道的是,通常已经存在的点 接近列表的末尾 。有时它在“批量”中,只是偶尔会在开头附近找到。
这让我想到了以相反的顺序进行搜索。但是,考虑到我可能会在这个过程中增长的庞大列表,我将如何最有效地做到这一点(就原始速度而言)。 list
容器在这里是最好的方法吗?
通过这样做我设法获得了一些性能
list_of_points = []
while True
# generate new point according to some rule
z = generate()
# check very end of list
if z in list_of_points[-10:]:
continue
# check deeper into the list
if z in list_of_points[-100:-10]:
continue
# check the rest
if z not in list_of_points[:-100]:
list_of_points.append(z)
if some_condition:
break
显然,这不是很优雅。使用第二个 FIFO 型容器 (collection.deque),可以提供大致相同的加速。
你最好的选择可能是使用集合而不是列表,python 集合使用散列来插入项目,所以速度非常快。而且,您可以跳过检查项目是否已在列表中的步骤,只需尝试添加它即可,如果它已经在集合中,则不会添加,因为不允许重复。
窃取你的伪代码示例
set_of_points = {}
while True
# get size of set
a = len(set_of_points)
# generate new point according to some rule
z = generate()
# try to add z to the set
set_of_points.add(z)
b = len(set_of_points)
# if a == b it was not added, thus already existed in the set
if some_condition:
break
使用 set
。这就是集合的用途。啊 - 你已经有了答案。所以我的其他评论:您的这部分代码似乎不正确:
# check the rest
if z not in list_of_points[100:]:
list_of_points.append(z)
在上下文中,我相信你打算在那里写 list_of_points[:-100]
。您已经检查了最后 100 个,但是,您现在跳过检查 first 100 个。
但更好的是,使用普通 list_of_points
。随着列表变长,与复制 len(list_of_points) - 100
个元素