Python大数组比较

时间:2016-10-19 11:43:20

标签: python arrays performance python-2.7 compare

我有一个包含URL的大型数组(它可以包含10万个URL字符串),我想知道我的实际URL是否是数组中的URL之一。为此,我必须将实际的URL字符串与数组中的所有URL字符串进行比较。有没有办法比较这个大阵列,但比我现在的时间少?现在它是:

error = 0
for oldUrl in urlList:
    error = 1 if oldUrl == actualUrl else error

3 个答案:

答案 0 :(得分:1)

要检查list是否包含item,请使用:item in list

所以,你可以写:

error = oldUrl in urlList

答案 1 :(得分:1)

正如@Laurent和@sisanared已经提到的,您可以使用in运算符来listssets来检查成员身份。例如:

found = x in some_list
if found: 
    #do stuff
else:
    #other stuff

但是,你提到速度是一个问题。如果sets已存在,则TL; DR - set会更快。从https://wiki.python.org/moin/TimeComplexity开始,使用in运算符检查成员资格为list的O(n)和set的O(1)(如@enderland所指出)。

对于100,000件物品,或者只进行一次性检查,它可能并没有太大的差别,但是对于大量的物品或者您要进行多次检查的情况,您应该使用set。我从解释器做了几个测试,这是我发现的(Python 2.7,i3 Windows 10 64bit):

import timeit
#Case 1: Timing includes building the list/set
def build_and_check_a_list(n):
    a_list = [ '/'.join( ('http:stackoverflow.com',str(i)) ) for i in xrange(1,n+1) ]
    check = '/'.join( ('http:stackoverflow.com',str(n)) )
    found = check in a_list
    return (a_list, found)

def build_and_check_a_set(n):
    a_set = set( [ '/'.join( ('http:stackoverflow.com',str(i)) ) for i in xrange(1,n+1) ] )
    check = '/'.join( ('http:stackoverflow.com',str(n)) )
    found = check in a_set
    return (a_set, found)

timeit.timeit('a_list, found = build_and_check_a_list(100000)', 'from __main__ import build_and_check_a_list', number=50)
3.211972302022332

timeit.timeit('a_set, found = build_and_check_a_set(100000)', 'from __main__ import build_and_check_a_set', number=50)
4.5497120006930345

#Case 2: The list/set already exists (timing excludes list/set creation)
check = '/'.join( ('http:stackoverflow.com',str(100000)) )

timeit.timeit('found = check in a_list', 'from __main__ import a_list, check', number=50)
0.12173540635194513

timeit.timeit('found = check in a_set', 'from __main__ import a_set, check', number=50)
1.01052391983103e-05

对于100万个条目,要在我的计算机上构建和/或检查成员资格:

#Case 1: list/set creation included
timeit.timeit('a_list, found = build_and_check_a_list(1000000)', 'from __main__ import build_and_check_a_list', number=50)
35.71641090788398

timeit.timeit('a_set, found = build_and_check_a_set(1000000)', 'from __main__ import build_and_check_a_set', number=50)
51.41244436103625

#Case 2: list/set already exists
check = '/'.join( ('http:stackoverflow.com',str(1000000)) )

timeit.timeit('found = check in a_list', 'from __main__ import a_list, check', number=50)
1.3113457772124093

timeit.timeit('found = check in a_set', 'from __main__ import a_set, check', number=50)
8.180430086213164e-06

答案 2 :(得分:0)

请勿使用此列表。列表中的查找具有O(n)的最坏情况复杂度。

使用集合(或字典,如果您有其他元数据)。这有一个大致为O(1)的查找。有关集合,字典和列表之间的比较,请参阅here

使用集合,查找很简单:

urls = set(['url1', 'url2', 'url3'])

print ('url2' in urls)
print ('foobar' in urls)

或者在您的情况下,将列表对象转换为集合:

urlListSet = set(urlList)
print(oldUrl in urlListSet)

您还可以在设置中添加新网址:

urlListSet.add(newurl)
urlListSet.update(listOfNewUrls)