2012-04-04 4 views
29

Diciamo che ho un string"Hello" e un elencoPython: trovare più vicino stringa (da una lista) ad un'altra stringa

words = ['hello', 'Hallo', 'hi', 'house', 'key', 'screen', 'hallo','question', 'Hallo', 'format'] 

Come posso trovare il n words che sono più vicino a "Hello" e presente nella lista words?

In questo caso, avremmo ['hello', 'hallo', 'Hallo', 'hi', 'format'...]

Quindi la strategia è quello di ordinare le parole della lista dalla parola più vicina alla più lontana.

ho pensato a qualcosa di simile

word = 'Hello' 
for i, item in enumerate(words): 
    if lower(item) > lower(word): 
     ... 

ma è molto lento in grandi liste.

UPDATE difflib funziona ma è anche molto lento. (words list contiene 630000+ parole all'interno (ordinate e una per riga)). Quindi controllare l'elenco richiede da 5 a 7 secondi per ogni ricerca della parola più vicina!

+6

Forse siete alla ricerca di qualcosa come la modifica a distanza o Levinshtein distanza? – tripleee

+3

Esattamente, questo dipende in gran parte da cosa è la tua definizione di "_closest_". –

+0

Le 630.000 parole sono ordinate? Sono in un file, una parola per riga? –

risposta

53

Utilizzare difflib.get_close_matches.

>>> words = ['hello', 'Hallo', 'hi', 'house', 'key', 'screen', 'hallo', 'question', 'format'] 
>>> difflib.get_close_matches('Hello', words) 
['hello', 'Hallo', 'hallo'] 

Consultare la documentazione, poiché la funzione restituisce 3 o meno corrispondenze più vicine per impostazione predefinita.

+7

Solo una rapida FYI: 'difflib.get_close_matches (" Hallo ", words, len (words), 0)' darebbe tutte le corrispondenze :) –

+3

La differenza Levenshtein può essere usata anche. C'è una buona implementazione di python http://pypi.python.org/pypi/python-Levenshtein/ –

+1

difflib funziona ma è anche molto lento. (l'elenco delle parole contiene 630000+ parole all'interno). Quindi controllare l'elenco richiede da 5 a 7 secondi per ogni ricerca della parola più vicina! – Laura

1

Creare un elenco ordinato delle parole e utilizzare lo bisect module per identificare il punto nell'elenco ordinato in cui la parola verrà adattata in base all'ordinamento. Basandoti su quella posizione puoi dare ai k vicini più vicini sopra e sotto per trovare le parole 2k più vicine.

+1

Sei sicuro che funzionerà? Non credo che l'ordine lessicografico sia ciò che l'OP vuole ... –

+0

Considerando il frammento di codice dalla domanda, una soluzione così semplice potrebbe essere tutto ciò che è necessario. – user1308520

+1

Questo non funzionerà se è possibile prendere in considerazione gli errori di ortografia, specialmente se si commettono errori all'inizio della parola. Ma una buona soluzione per parole corrette davvero. – laurasia

14

C'è un articolo fantastico con un codice sorgente completo (21 righe) fornito da Peter Norvig sulla correzione ortografica.

http://norvig.com/spell-correct.html

L'idea è quella di costruire tutte le possibili modifiche della tua parola,

hello - helo - deletes  
hello - helol - transpose  
hello - hallo - replaces  
hello - heallo - inserts  


def edits1(word): 
    splits  = [(word[:i], word[i:]) for i in range(len(word) + 1)] 
    deletes = [a + b[1:] for a, b in splits if b] 
    transposes = [a + b[1] + b[0] + b[2:] for a, b in splits if len(b)>1] 
    replaces = [a + c + b[1:] for a, b in splits for c in alphabet if b] 
    inserts = [a + c + b  for a, b in splits for c in alphabet] 
    return set(deletes + transposes + replaces + inserts) 

Ora, guardare in alto ognuna di queste modifiche nella vostra lista.

L'articolo di Peter è un'ottima lettura e vale la pena leggerlo.

+0

Grazie, questa è una grande scoperta. Sto scrivendo un dizionario integrato e questo potrebbe essere utile. – laurasia

0

forse heap può aiutarti.

avete un mucchio di nome Heap che fino a quando la sua dimensione è inferiore a n, si inserisce le parole nella Heap tramite la funzione close [mostra questa stringa è più vicino di un'altra stringa o meno].

Questo metodo può aiutare quando n è piccolo :)

Heap = [] 
for word in words: 
    if len(Heap)<n: 
     Heap.insert(word) 
    else 
     if close(word,Heap[0]): # it means Heap[0] is the nth farthest word until now 
      Heap.pop(): 
      Heap.insert(word) 
Problemi correlati