2012-04-04 10 views
29

Digamos que tengo un string"Hello" y una listaPython: encontrar la cadena más cercano (de una lista) a otra cadena

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

¿Cómo puedo encontrar el n words que son los más cercanos a "Hello" y en la lista words?

En este caso, tendríamos ['hello', 'hallo', 'Hallo', 'hi', 'format'...]

Así que la estrategia es ordenar las palabras de la lista de la palabra más cercana a la más lejana.

pensé en algo como esto

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

pero es muy lento en grandes listas.

ACTUALIZACIÓN difflib funciona pero también es muy lento. (words list tiene más de 630000 palabras adentro (ordenadas y una por línea)). ¡Así que consultar la lista lleva de 5 a 7 segundos para cada búsqueda de palabra más cercana!

+6

Quizás esté buscando algo así como la distancia de edición o Levinshtein distancia? – tripleee

+3

Exactamente, esto depende en gran medida de lo que sea su definición de '_closest_'. –

+0

¿Están las 630,000 palabras ordenadas? ¿Están en un archivo, una palabra por línea? –

Respuesta

53

Use difflib.get_close_matches.

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

Consulte la documentación, ya que la función devuelve 3 o menos coincidencias más cercanas de forma predeterminada.

+7

Solo un rápido FYI: 'difflib.get_close_matches (" Hallo ", words, len (words), 0)' daría todas las coincidencias :) –

+3

La diferencia de Levenshtein puede usarse también. Hay una buena implementación de Python http://pypi.python.org/pypi/python-Levenshtein/ –

+1

difflib funciona pero también es muy lento. (la lista de palabras tiene 630000+ palabras dentro). ¡Así que consultar la lista lleva de 5 a 7 segundos para cada búsqueda de palabra más cercana! – Laura

1

Cree una lista ordenada de sus palabras y use bisect module para identificar el punto en la lista ordenada donde su palabra cabría según el orden de clasificación. En función de esa posición, puede dar a los k vecinos más cercanos arriba y abajo para encontrar las 2k palabras más cercanas.

+1

¿Estás seguro de que esto funcionará? No creo que el orden lexicográfico sea lo que OP quiere ... –

+0

Teniendo en cuenta el fragmento de código de la pregunta, una solución tan simple podría ser todo lo que se necesita. – user1308520

+1

Esto no funcionará si es posible que se tengan en cuenta los errores ortográficos, especialmente si se cometen errores al comienzo de la palabra. Pero una buena solución para palabras correctas de hecho. – laurasia

14

Hay un artículo impresionante con un código fuente completo (21 líneas) proporcionado por Peter Norvig sobre la corrección ortográfica.

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

La idea es construir todas las posibles modificaciones de su palabra,

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) 

Ahora, mira hacia arriba cada una de estas ediciones en su lista.

El artículo de Peter es de gran lectura y vale la pena leerlo.

+0

Gracias, eso es un gran hallazgo. Estoy escribiendo un diccionario integrado y esto podría ser útil. – laurasia

0

tal vez heap puede ayudarlo.

usted tiene un montón nombrado Heap que hasta su tamaño es menor que n, insertar las palabras en el uso de la función Heapclose [muestra esta cadena está más cerca que otra cadena o no].

este método puede ayudar a usted cuando n es pequeña :)

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) 
Cuestiones relacionadas