2010-06-03 13 views
5

In PHP, ho avuto questa riga matches = preg_grep('/^for/', array_keys($hash)); Che cosa sarebbe fare sarebbe prendere le parole: fork, form ecc. Che sono in $ hash.funzione di completamento automatico con un pitone dict

In Python, ho un ditt con 400.000 parole. Le sue chiavi sono parole che vorrei presentare in una funzione di completamento automatico (i valori in questo caso sono privi di significato). Come potrei restituire le chiavi dal mio dizionario che corrispondono all'ingresso?

Per esempio (come quello usato in precedenza), se ho

my_dic = t{"fork" : True, "form" : True, "fold" : True, "fame" : True} 

e ottengo alcuni input "for", sarà restituito un elenco di "fork", "form".

+0

''fold'' non sarebbe molto'' for'' – SilentGhost

+0

SilentGhost: sei assolutamente corretto, modificato. – tipu

risposta

6
>>> mydict={"fork" : True, "form" : True, "fold" : True, "fame" : True} 
>>> [k for k in mydict if k.startswith("for")] 
['fork', 'form'] 

Questo dovrebbe essere più veloce di usare un'espressione regolare (e sufficiente se stai solo cercando l'inizio di una parola).

1
>>> my_dict = {"fork" : True, "form" : True, "fold" : True, "fame" : True} 
>>> import re 
>>> [s for s in my_dict if re.search('^for', s) is not None] 
['fork', 'form'] 

L'utilizzo di espressioni regolari è più universale, come si potrebbe fornire modelli di ricerca più complessi, se è solo circa prefissi, è possibile utilizzare metodi delle stringhe: str.startwith, ad esempio:

>>> [s for s in my_dict if s.startswith('for')] 
['fork', 'form'] 
0

È possibile ottenere le chiavi da my_dict con my_dict.keys(). Quindi, puoi cercare attraverso ogni chiave per vedere se corrisponde alla tua espressione regolare.

m = re.compile('^for') 
keys = [] 
for key in my_dict.keys(): 
    if m.match(key) != None: 
     keys.append(key) 
3

Quindi questa non è una risposta diretta a quello che chiedi, ma ..

Sembra che non si vuole veramente un dict per questo genere di cose, siete alla ricerca di un struttura ad albero, giusto?

Quindi è possibile percorrere l'albero per ogni lettera digitata (tempo costante) e restituire le foglie da tale sottosezione dell'albero come le parole che corrispondono a tale prefisso.

+0

Questo caso particolare non è l'unica volta che sto usando il dict. È un indice invertito, quindi i valori sono un insieme di ID documento che sono assolutamente vitali per quello che sto facendo. La ragione per cui sto usando un dict è perché la ricerca sarà molto più veloce di un albero (la memoria è abbondante, i cicli della CPU non lo sono) – tipu

+0

Anche se la ricerca delle chiavi note sarà più veloce con una struttura ad albero, dover testare ogni la chiave per una corrispondenza parziale non sarà - quindi nei casi in cui non si conosce la chiave in anticipo (come quella che si presenta, sopra) qualcosa di un po 'più simile ad un albero sarebbe meglio. – pycruft

+2

Fyi, la struttura dati perfetta per questo problema è chiamata ** trie ** - ma lo stdlib di python non ne ha uno. –

1

Se si desidera una strategia di ricerca specifica (ad esempio "startswith 3 caratteri" descritta sopra), è possibile ottenere una rapida vittoria creando un dizionario di ricerca specifico basato su tale idea.

q = {"fork":1, "form":2, "fold":3, "fame":4} 
from collections import defaultdict 
q1 = defaultdict(dict) 
for k,v in q.items(): 
    q1[k[:3]][k]=v 

Ciò consente di fare un .startswith tipo di ricerca nel corso di un molto più piccolo set

def getChoices(frag): 
    d = q1.get(frag[:3]) 
    if d is None: 
     return [] 
    return [ k for k in d.keys() if k.startswith(frag) ] 

Speriamo che dovrebbe essere molto più veloce di elaborazione dell'intero 400.000 chiavi.

Problemi correlati