遍历集合还是列表更好/更快?

40 投票
6 回答
105229 浏览
提问于 2025-04-17 17:15

如果我有一个包含很多重复元素的Python列表,我想遍历每个项目,但不想遍历重复的部分,使用集合(比如 set(mylist))是否是最好的选择,还是有其他方法可以创建一个没有重复的列表?我原本想直接遍历这个列表并检查重复项,但我想这正是 set() 在初始化时所做的事情。

比如说,如果 mylist = [3,1,5,2,4,4,1,4,2,5,1,3],我其实只想遍历 [1,2,3,4,5](顺序无所谓),我应该使用 set(mylist) 还是其他方法呢?

在最后这个例子中,还有另一种可能性,因为这个列表包含了它的最小值和最大值之间的每一个整数,我可以遍历 range(min(mylist),max(mylist)) 或者使用 set(mylist)。在这种情况下,我应该尽量避免使用集合吗?另外,找到 minmax 的速度会比直接创建 set 慢吗?


在最后这个例子中,使用 set 更快:

from numpy.random import random_integers
ids = random_integers(1e3,size=1e6)

def set_loop(mylist):
    idlist = []
    for id in set(mylist):
        idlist.append(id)
    return idlist

def list_loop(mylist):
    idlist = []
    for id in range(min(mylist),max(mylist)):
        idlist.append(id)
    return idlist

%timeit set_loop(ids)
#1 loops, best of 3: 232 ms per loop

%timeit list_loop(ids)
#1 loops, best of 3: 408 ms per loop

6 个回答

8

虽然从结构上看,set 可能是你想要的,但问题是哪个更快。其实,list 更快。你的示例代码没有准确比较 setlist,因为你在 set_loop 中把一个列表转换成了一个集合,然后在 list_loop 中又创建了一个要循环的列表。你在循环中使用的集合和列表应该提前构建好并存储在内存中,然后直接循环查看哪个数据结构在遍历时更快:

ids_list = range(1000000)
ids_set = set(ids)
def f(x):
    for i in x:
         pass

%timeit f(ids_set)
#1 loops, best of 3: 214 ms per loop
%timeit f(ids_list)
#1 loops, best of 3: 176 ms per loop
10

你想要的就是 set,所以就应该使用 set。如果想要聪明一点,可能会引入一些难以发现的错误,比如忘记在 max(mylist) 的结果上加一!编程的时候要小心谨慎。等你发现速度太慢的时候,再考虑怎么优化速度。

range(min(mylist), max(mylist) + 1)  # <-- don't forget to add 1
39

直接用一个 set 就行。它的意思正好符合你的需求:就是一堆不重复的东西。

从技术上讲,你会遍历这个列表两次:第一次是为了创建这个集合,第二次是你真正需要的循环。但其实用其他方法做也是差不多的工作量,甚至可能更多。

撰写回答