2009-12-04 4 views
1

약 1000 개의 키워드/문구 (1 ~ 4 단어 길이)가있는 데이터베이스 테이블이 있습니다.이 테이블은 거의 변경되지 않으므로 데이터를 더 유용한 것으로 추출 할 수 있습니다 (정규 표현식처럼?) - 자연어 처리에 기반한 키워드를 찾거나 추측하지 못합니다.저장된 키워드/문구가 텍스트와 일치합니다.

그런 다음 사용자가 내 키워드 및 구문과 일치하는 양식에 텍스트를 입력하게하십시오.

그러면 프로그램은 텍스트 옆에 일치하는 각 구에 대한 링크를 저장합니다. 우리가 여기에 몇 가지 문구에 대해이 질문 텍스트의 알고리즘을 실행 한 경우

그래서, 우리가 지금과 같은 결과를 얻을 것 :

{"inputting some text" : 1, 
"extract the data" : 1, 
"a phrase not here" : 0} 

을 내 옵션은 무엇입니까?

  1. 는 정규 표현식
  2. SQL 쿼리
  3. 세 번째 방법의 일종 컴파일? 1000 명 가능한 문구를가 있다는 것을 염두에

베어링 ...

나는 MySQL과 장고/파이썬을 실행하고 있습니다. 나는 현재이 일을 해요 : :

편집 내가 제대로 이해하면

>>> text_input = "This is something with first phrase in and third phrase" 
>>> regex = "first phrase|second phrase|third phrase" 
>>> p = re.compile(regex, re.I) 
>>> p.findall(text_input) 
['first phrase','third phrase'] 

답변

1

알고리즘은 Aho-Corasick입니다 파이썬을위한 C-확장을 가리키는 whch 하단의 링크를 참조하십시오.

0

, 당신은 당신이에 대해 입력 문자열을 비교하려는 문자열의 독특한 있습니다. 이 경우 처리 결과와 db 값을 모두 저장하려면 set을 사용할 수 있습니다. 다음과 같이 비교를 수행 할 수 있습니다.

>>> db = {'abc', 'def', 'jhi', 'asdf'} 
>>> inpt = {'abc', 'tmp'} 
>>> db & inpt 
{'abc'} 

사전에 대한 추가 변환은 간단합니다.

+0

잘 - 종류. 나는 그 블록 내에서 내가 찾고있는 텍스트와 구획 블록을 가지고있다. 저는 현재 다음과 같은 정규 표현식을 사용하고 있습니다 : >>> text_input = "이것은 첫 번째 구 및 첫 번째 구가" "일 수 있습니다. >>> regex ="첫 번째 구 | 두 번째 구 | 세 번째 구 " > >> p = re.compile (정규식, re.I) >>> p.findall (TEXT_INPUT) [ '제 구문', '제 문구'] –

+0

FWIW는 문법 세트 이해 파이썬 3.0 이상이다. – hughdbrown

+0

@hughdbrown : 나는 새로운 스타일 세트 리터럴 http://docs.python.org/3.1/whatsnew/3.0.html#new-syntax 여기에 모든 것이 평 2에서 수행 될 수를 사용하고, 세트 이해를 사용하지 않았다. x를 사용하여'set (lst)' – SilentGhost

0

는 SilentGhost의 대답에 약간의 변형입니다. 키워드를 줄 단위로로드합니다. 그것들을 세트에 보관하십시오. 사용자 입력에서 찾은 각 키워드에 대해 결과의 해당 항목이 증가합니다.

keyword_file = StringIO("""inputting some text 
    extract the data 
    a phrase not here""") 

keywords = set(line.strip() for line in keyword_file) 

results = defaultdict(int) 
for phrase in keywords: 
    if userinput.find(phrase) != -1: 
     results[phrase] += 1 

print results 

희망이 있으면 올바른 방향으로 인도합니다. 이것이 당신이 묻고있는 것이 아니라는 것이 확실하지는 않습니다. 그러나 그것은 나의 가장 좋은 추측입니다.

속도에 신경 씁니까? 왜 지금 당신이 사용하는 방법을 좋아하지 않아? 당신의 방법은 효과가 있습니까?당신은 그런 (first phrase)|(the second)|(and another) ( 내가 나타내는 괄호 )로 패턴을 형성하고 정규 표현식 객체 r, 경기에 루프 좋은 방법으로 컴파일하고 그것이 일치를 식별 한 후

0

은 다음과 같습니다

정규식 자체와 동일한 순서로 구의 목록이 필요하므로 GroupCounter 인스턴스도 정규식 개체를 작성하는 것이 타당합니다.

0

는 1000 개 문구가있는 경우, 당신은 문자열있는 그 문구 어떤 찾기 위해 입력 문자열을 검색하는, 당신은 아마 당신은 큰 정규 표현식을 사용에서 얻는 성능에 행복하지 않을거야. trie 구현하기 위해 조금 더 많은 작업이지만, 훨씬 더 효율적입니다 : a|b|c|d|e 주어진 입력 문자열의 각 문자에 5 개 테스트를 수행하는 정규 표현식하는 트라이 하나만 않지만. Plex과 같은 DFA를 생성하는 렉서 (lexer)를 사용할 수도 있습니다.

편집 :

는 오늘 아침을 미루는 것으로 나타났습니다. 이 시도 :

class Trie(object): 
     def __init__(self): 
      self.children = {} 
      self.item = None 
     def add(self, item, remainder=None): 
      """Add an item to the trie.""" 
      if remainder == None: 
       remainder = item 
      if remainder == "": 
       self.item = item 
      else: 
       ch = remainder[0] 
       if not self.children.has_key(ch): 
        self.children[ch] = Trie() 
       self.children[ch].add(item, remainder[1:]) 
     def find(self, word): 
      """Return True if word is an item in the trie.""" 
      if not word: 
       return True 
      ch = word[0] 
      if not self.children.has_key(ch): 
       return False 
      return self.children[ch].find(word[1:]) 
     def find_words(self, word, results=None): 
      """Find all items in the trie that word begins with.""" 
      if results == None: 
       results = [] 
      if self.item: 
       results.append(self.item) 
      if not word: 
       return results 
      ch = word[0] 
      if not self.children.has_key(ch): 
       return results 
      return self.children[ch].find_words(word[1:], results) 

빠른 테스트 (words.txt이 매우 편리한 것은 주위가하는 BSD 워드 파일 - 그것은 약 240,000 단어 포함) :

>>> t = Trie() 
>>> with open(r'c:\temp\words.txt', 'r') as f: 
     for word in f: 
      t.add(word.strip()) 

에 약 15 초 정도 걸립니다 내 기계. 그러나 이것은 거의 순간적 :

>>> s = "I played video games in a drunken haze." 
>>> r = [] 
>>> for i in range(len(s)): 
     r.extend(t.find_words(s[i:])) 
>>> r 
['I', 'p', 'play', 'l', 'la', 'lay', 'a', 'ay', 'aye', 'y', 'ye', 'yed', 'e', 'd', 'v', 'video', 'i', 'id', 'ide', 'd', 'de', 'e', 'o', 'g', 'ga', 'gam', 'game', 'a', 'am', 'ame', 'm', 'me', 'e', 'es', 's', 'i', 'in', 'n', 'a', 'd', 'drunk', 'drunken', 'r', 'run', 'u', 'un', 'unken', 'n', 'k', 'ken', 'e', 'en', 'n', 'h', 'ha', 'haze', 'a', 'z', 'e'] 

예, unken이 words.txt입니다. 나는 이유를 모른다.

아, 그리고 정규 표현식과 비교하려고 않았다 ...이 작업

>>> import re 
>>> with open(r'c:\temp\words.txt', 'r') as f: 
     p = "|".join([l.strip() for l in f]) 

>>> p = re.compile(p) 

Traceback (most recent call last): 
    File "<pyshell#250>", line 1, in <module> 
    p = re.compile(p) 
    File "C:\Python26\lib\re.py", line 188, in compile 
    return _compile(pattern, flags) 
    File "C:\Python26\lib\re.py", line 241, in _compile 
    p = sre_compile.compile(pattern, flags) 
    File "C:\Python26\lib\sre_compile.py", line 529, in compile 
    groupindex, indexgroup 
OverflowError: regular expression code size limit exceeded 
+0

은 @johnmachin에 의해 제안 아호-Corasick 건과 비슷한 것 같다 - 두 ... –

+0

아호-Corasick가 빠른 사이의 속도 차이에 관심이있을 것입니다. 그러나 둘 사이의 속도 차이는 사전 검색의 크기가 아니라 검색되는 문자열 길이의 함수입니다. 상대적으로 긴 문자열을 검색하는 경우 추가 복잡성이 필요할 것입니다. –