2013-02-27 55 views
28

如果我有一个Python列表是有很多重复,我想通过每个项目迭代,但不是通过重复的,是它最好使用一组(如set(mylist),或者找到另一种方式来创建一个列表,而不重复?我是通过[1,2,3,4,5]思考的只是通过列表循环和检查重复,但我想这是当它的初始化set()做什么。更好/更快通过设置或列表循环?

所以,如果mylist = [3,1,5,2,4,4,1,4,2,5,1,3],我真的只是想环路(顺序并不重要),我应该使用set(mylist)还是其他什么东西?

另一种可能是在最后一个例子,因为该列表包含了分钟和M之间的每个整数ax值,我可以循环通过range(min(mylist),max(mylist))或通过set(mylist)。我通常应该尽量避免在这种情况下使用set?此外,找到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 
+0

为什么不试一下吗? – 2013-02-27 00:30:59

+2

@JoelCornett完成:) – askewchan 2013-02-27 00:33:10

+0

您是否期望这种速度差异在您编写的任何程序中都很重要?使用genexp保持事物,使用genexp而不是构建一个百万个元素的'list'来迭代(如果这是Py2,则使用'xrange'而不是'range'),试图在C中做紧密循环的Python(例如'idlist = range(...)'而不是执行相同操作的'for'循环)等都会产生更大的差异。 – abarnert 2013-02-27 01:56:43

回答

33

只需使用一个set。它的语义正是你想要的:一系列独特的项目。

从技术上讲,你会通过列表迭代两次:一次为您的实际循环创建集,一次。但是你会用其他方法做同样多的工作或更多。

+0

使用一个发电机和一套将只循环一次,看看我的答案我会爱你的意见。@ Eevee – Cherif 2017-11-03 08:07:35

3

为了简便起见:newList = list(set(oldList))

但也有更好的选择了,如果你想获得速度/排序/优化,而不是:http://www.peterbe.com/plog/uniqifiers-benchmark

+3

没有理由回到清单。在将其转换为集合时,他已经失去了元素顺序,所以没有理由不停留在集合中。 – ThiefMaster 2013-02-27 00:32:19

+0

@ThiefMaster有理由想回到名单,主要是表现。迭代的列表要比集合快得多,并且通过为每个元素保留一个内部属性,您可以轻松地将其转换回列表并按照正确的顺序排序。 – Flipper 2015-01-08 23:31:57

9

set是你想要的,所以你应该使用set 。试图聪明地引入微妙的错误,如忘记添加一个到max(mylist)!代码防守。担心在确定速度太慢时速度会更快。

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

我很想在这里看到你对我的回答的看法,就是我们处理大名单时很快。 – Cherif 2017-11-03 08:10:46

4

虽然set可能是你想要的结构明智的,问题是什么是速度更快。列表更快。您的示例代码不准确比较set VS list因为你从列表中set_loop转换为一组,然后要创建的list,你会通过将循环在list_loop。该组并列出您完成应当建立并在内存中的时间提前迭代,并简单地循环通过看哪个数据结构是在迭代速度快:

ids_list = range(1000000) 
sids_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 
1

我的名单变化大循环两个时间过它会在第二次循环集合而不是列表时需要花费很多时间和更多时间,并且我们知道遍历集合比列表慢。

我认为你需要的generatorset电源。

def first_test(): 

    def loop_one_time(my_list): 
     # create a set to keep the items. 
     iterated_items = set() 
     # as we know iterating over list is faster then list. 
     for value in my_list: 
      # as we know checking if element exist in set is very fast not 
      # metter the size of the set. 
      if value not in iterated_items: 
       iterated_items.add(value) # add this item to list 
       yield value 


    mylist = [3,1,5,2,4,4,1,4,2,5,1,3] 

    for v in loop_one_time(mylist):pass 



def second_test(): 
    mylist = [3,1,5,2,4,4,1,4,2,5,1,3] 
    s = set(mylist) 
    for v in s:pass 


import timeit 

print(timeit.timeit('first_test()', setup='from __main__ import first_test', number=10000)) 
print(timeit.timeit('second_test()', setup='from __main__ import second_test', number=10000)) 

出认沽:

0.024003583388435043 
    0.010424674188938422 

注:此方法才能保证