2012-04-24 2 views
0

다른 목록에서 한 목록을 필터링하는 좋은 방법을 찾고 있는데, 먼저 두 번째 목록의 부분 문자열을 일치시키고 싶습니다. 파이썬에서 다른 단어 목록 (하위 문자열)의 목록으로

이 구체적으로 : 내가 URL을 목록 1을 가지고 같은리스트 2 : URL을

['microsoft.com', 'ibm.com', 'cnn', '.ru'] etc 

첫 번째 목록은 거대하다 (항목의 수천), 두 번째 목록은 500-1000처럼 작다. 그러나 두 번째 목록 항목을 하위 문자열 검색으로 사용해야하므로 "in"또는 집합을 사용하는 단순 일치는 충분하지 않습니다. 내가 생각할 수있는 것은 두 개의 "for"루프라고 생각할 수 있지만 파이썬으로는 보이지 않습니다.

PS 일치하는 항목을 첫 번째 목록에서 제거하는 것이 목적입니다.

+0

수천 개가 특히 크지 않습니다. 수십만 명이 거대한 것을 얻고 있습니다. – MattH

+0

여전히 시간이 걸립니다. 예를 들어 2000/2000 목록의 경우 간단한 전체 문자열 일치가 2 초가 걸립니다. >>> list1 = filter (lambda x : list.list1에없는 x.lower()) 하지만 하위 문자열을 확인해야합니다. filter()와 같은 효과적인 방법을 찾지 못했습니다 ... – alex29

+0

필터 목록을 제한 할 수 있습니까? 당신의보기 중, 단 하나는'endswith '이지 않는 것처럼 보입니다? – MattH

답변

3

일치시킬 문자열에서 하나의 분리 된 일반 표현식을 만든 다음 RE 개체의 search 메서드를 사용하여 일치를 수행 할 수 있습니다. RE에 붙여 넣기 전에 문자열을 re.escape으로 확인하십시오.

>>> import re 
>>> substrings = ['microsoft.com', 'ibm.com', 'cnn', '.ru'] 
>>> pattern = "(?:%s)" % "|".join(map(re.escape, substrings)) 
>>> print(pattern) 
(?:microsoft\.com|ibm\.com|cnn|\.ru) 
>>> pattern = re.compile(pattern) 
>>> [x for x in ["www.microsoft.com", "example.com", "foo.ru"] 
... if not pattern.search(x)] 
['example.com'] 
+1

이것은 놀랍도록 빠르다. 나는 단순 문자열 검색이 re를 사용하는 것보다 빠르다고 믿었지만,이 솔루션은 16000과 1000 목록의 경우 2 초 밖에 걸리지 않습니다. 나는 이미 두 개의 목록을 일치시키기 위해 이런 식으로 만들었지 만, 전체 일치로 두 번째 목록을 문자열에 연결하고 검색을 사용했지만 부분 검색에 re를 사용하는 아이디어는 멋지다 :) – alex29

0

예상 한 내용입니까?

one=['microsoft.com', 'ibm.com', 'cnn', '.ru'] 
two=['.com'] 
filtered=[o for o in one for t in two if o.find(t)!=-1] 
+0

그건 아니야 - 나는 항목을 걸러 낼 필요가있어. 두 번째 목록에없는 항목 만 남겨두면 모든 .find() 결과를 확인하고 모두 음수이면 항목 만 남겨 두어야합니다. – alex29

관련 문제