2011-12-30 22 views
5

Ho una funzione che cerca una stringa in una lista di liste quindi restituisce una lista contenente le liste corrispondenti:Python stringa avanzata ricerca con gli operatori e booleano

def foo(myList,keyword,first=True): 
    if first: #Search only first element or each sublist 
     return [x for x in myList if keyword in x] 
    else: #Search first and second elements of each sublist 
     return [x for x in myList if keyword in x or keyword in x[1]] 

ora voglio estenderlo a gestire la ricerca avanzata con domande come:

matchthis -butnothis -"and not this" 

this|orthis|"or this" 

brand new*laptop # this is a wildcard, matches like: brand new dell laptop 

"exact phrase" 

Esistono moduli Python (preferibilmente incorporato) che posso usare nella mia funzione di gestire queste domande?

PS: Sono a conoscenza di Swoosh ma al momento non è la soluzione giusta per me. Inoltre, attualmente sto usando App Engine.

Quello che sto cercando di fare fondamentalmente è la ricerca full-text in memoria, dal momento che il motore di app non supporta ancora la ricerca full-text. Interrogo il datastore, metto le entità in liste e faccio il giro di questi elenchi per trovare le corrispondenze delle query.

risposta

4

Proverei a costruire un'espressione regolare per ogni parte della query di ricerca. In primo luogo è possibile suddividere la query nelle porzioni utilizzando shlex.split() e quindi creare ciascuna espressione regolare singolarmente. Qui è la mia crepa a esso:

import shlex, re 

def foo(query): 
    pieces = shlex.split(query) 
    include, exclude = [], [] 
    for piece in pieces: 
     if piece.startswith('-'): 
      exclude.append(re.compile(piece[1:])) 
     else: 
      include.append(re.compile(piece)) 
    def validator(s): 
     return (all(r.search(s) for r in include) and 
       not any(r.search(s) for r in exclude)) 
    return validator 

Ciò restituirà una funzione che è possibile utilizzare per convalidare contro la query, ad esempio:

>>> test = foo('matchthis -butnothis -"and not this"') 
>>> test("we should matchthis...") 
True 
>>> test("some stuff matchthis blah and not this...") 
False 

si dovrebbe essere in grado di aggiungere in qualche manipolazione da parte jolly sostituendo * nella query con .* nell'espressione regolare.

+0

questo sembra molto promettente, lasciatemi fare un tentativo. – ofko

+0

questa è la perfezione! Grazie. – ofko

2

Non esiste un modulo di libreria standard che faccia tutto ciò che si desidera; tuttavia, è possibile iniziare con la shlex module per analizzare i gruppi di ricerca:

>>> import shlex 
>>> s = '''matchthis -butnothis -"and not this" 
this|orthis|"or this" 
brand new*laptop 
"exact phrase" 
''' 
>>> shlex.split(s) 
['matchthis', '-butnothis', '-and not this', 'this|orthis|or this', 'brand', 'new*laptop', 'exact phrase'] 

È inoltre possibile guardare il re module nel caso in cui avete bisogno di più controllo a grana fine sopra il parsing.

+0

Ho pensato di usare espressioni regolari, ma ho l'impressione che sarebbe molto lento per un elenco di circa 1000 lunghezze con ogni testo in paragrafi o due. – ofko

+0

Se si precompilano le regex, possono essere molto veloci e difficili da battere con qualsiasi altra tecnica puramente Python. –

Problemi correlati