2012-06-04 6 views
1

사용자가 사이트 목록을 방문했는지 확인하기 위해 프록시 로그를 거쳐야하는 문제가 발생했습니다. "x in []"x의 {x} 검색 시간

나는 목록에 대한 방문 호스트와 일치하는 모든 프록시 로그를 읽을 수있는 작은 스크립트를 썼습니다 :

for proxyfile in proxyfiles: 
    for line in proxyfile.readlines(): 
     if line[4] in hosts_list: 
      print line 

hosts_file 큰, 우리가 ~ 10000 개 호스트에 대해 얘기하고, 나는 검색이 이상했다 발견 예상보다. 내 질문에, 그래서

list: 5.58524107933 
dict: 0.195574045181 

:

import random, time 
test_list = [x for x in range(10000)] 
test_dict = dict(zip(test_list, [True for x in range(10000)])) 

def test(test_obj): 
s_time = time.time() 
for i in range(10000): 
    random.randint(0,10000) in test_obj 
d_time = time.time() - s_time 
return d_time 

print "list:", test(test_list) 
print "dict:",test(test_dict) 

결과 것은 다음과 같다 :

나는 작은 시험을 썼다. 이 검색을보다 편리하게 수행 할 수 있습니까? 목록의 사전을 만드는 것은 해킹처럼 보입니다. 내가 포함하고있는 값이 아닌 키를 검색하려고합니다.

+3

코드 스 니펫을 테스트 할 때 직접 코드를 작성하는 대신 [timeit module] (http://docs.python.org/library/timeit.html#examples)을 사용할 수 있습니다. (ipython을 사용하면 더 쉽습니다.) – DSM

+3

타이밍 관찰에 * dict를 포함시켜야합니다. –

+7

세트를 사용할 수 있습니다. –

답변

5

=> 그럼 그냥 당신이 새로운 파이썬에 설정, 그런 일을 위해 사전을 사용하도록 동의 set

+0

좋은 생각, 불행히도이 경우 나는 파이썬 2.2에 묶여있다. 그러나 set()의 사용은 실행 가능한 해결책이라는 것에 동의합니다. –

+6

집합의 기본 구현은 기본적으로 키와 값이없는 사전입니다. Python 2.2에서는 사전을 사용하십시오. – casevh

+0

ActiveState에서 이전 설정된 레시피를 검색합니다. 거기에 몇 가지 있습니다. –

2

을 사용하여 "나는 그들이 키가 아닌 값을 검색 할 수 원하는대로 그것은 포함" , 응용 프로그램에서 가능하다면 2.2보다 새로운 python으로 이동하는 것을 고려하십시오.

그러나 목록이 정렬 된 순서이면 bisect 모듈을 사용하여 목록을 빠르게 검색하여 요소를 찾을 수 있습니다. dict만큼 빠르지 만 꽤 가깝습니다. (2.7에서 테스트)에 대한

import random, time 
import bisect 

class BisectContainsList(list): 
    def __contains__(self, elem): 
     i = bisect.bisect_left(self, elem) 
     if i != len(self) and self[i] == elem: 
      return True 
     return False 

test_list = [x for x in range(10000)] 
test_dict = dict(zip(test_list, [True for x in range(10000)])) 
test_blist = BisectContainsList(test_list) 

def test(test_obj): 
s_time = time.time() 
for i in range(10000): 
    random.randint(0,10000) in test_obj 
d_time = time.time() - s_time 
return d_time 

print "list:", test(test_list) 
print "dict:", test(test_dict) 
print "blist", test(test_blist) 

:

list: 1.19566082954 
dict: 0.0248260498047 
blist 0.0598628520966 
1

목록은이 도우미 함수와 bisect 모듈을 사용할 수 있습니다 분류 된 경우 :

def sorted_list_contains(alist, item): 
    i = bisect.bisect_left(alist, item) 
    return i != len(alist) and alist[i] == item 

편집 : 내가 한 내가 게시했을 때 bisect을 사용하여 Matt Anderson의 답변을 볼 수 없습니다. 이것을 대체 구현으로 남겨 두겠습니다.