Detecta las palabras más probables del texto sin espacios / palabras combinadas

¿Existe una buena biblioteca que pueda detectar y dividir palabras de una cadena combinada?

Ejemplo:

"cdimage" -> ["cd", "image"] "filesaveas" -> ["file", "save", "as"] 

Aquí hay una solución de progtwigción dinámica (implementada como una función memorizada). Dado un diccionario de palabras con sus frecuencias, se divide el texto de entrada en las posiciones que dan la frase más probable en general. Tendrá que encontrar una lista de palabras real, pero incluí algunas frecuencias inventadas para una prueba simple.

 WORD_FREQUENCIES = { 'file': 0.00123, 'files': 0.00124, 'save': 0.002, 'ave': 0.00001, 'as': 0.00555 } def split_text(text, word_frequencies, cache): if text in cache: return cache[text] if not text: return 1, [] best_freq, best_split = 0, [] for i in xrange(1, len(text) + 1): word, remainder = text[:i], text[i:] freq = word_frequencies.get(word, None) if freq: remainder_freq, remainder = split_text( remainder, word_frequencies, cache) freq *= remainder_freq if freq > best_freq: best_freq = freq best_split = [word] + remainder cache[text] = (best_freq, best_split) return cache[text] print split_text('filesaveas', WORD_FREQUENCIES, {}) --> (1.3653e-08, ['file', 'save', 'as']) 

No conozco ninguna biblioteca para eso, pero no debería ser difícil implementar una funcionalidad básica.

  1. Obtener una lista de palabras, como las words de UNIX.
  2. Guarde el contenido de su lista de palabras en un trie.
  3. Tome la cadena que desea dividir y siga su ruta en el trie. Cada vez que llegue a una palabra válida, cree una nueva twig que busque una palabra a partir del punto de la cadena a la que llegó. Una vez que termine su twig actual, retroceda a la que creó, como en una primera búsqueda en profundidad.
  4. Desambigüe las listas resultantes manualmente, utilizando heurísticas o mediante un analizador de lenguaje natural.

Ejemplo:

  1. Palabra: “filesaveasstring”
  2. La primera palabra válida es “archivo”. Intente hacer coincidir “saveas”. La primera palabra válida es “guardar”. Intente hacer coincidir “asstring”. La primera palabra válida es “como”. Intente hacer coincidir “cadena”. La primera palabra válida es “cadena”. Emparejado hasta el final; ponga el [archivo guardar como cadena] en su lista de resultados.
  3. Retroceder a la “cadena” correspondiente – no hay otras posibilidades. Retroceder a “asstring”. La primera palabra válida no visitada es “culo”. Intente hacer coincidir “tring”. No hay partidos posibles. Retroceder a “asstring”. No hay partidos posibles. Retrocede a “filesaveasstring”.
  4. La primera coincidencia no visitada es “archivos”. Intenta hacer coincidir “aveasstring”. El primer partido es “ave”. Intente hacer coincidir “asstring” (los mismos resultados que en los pasos 2/3), agregando [archivos ave como cadena] a su lista de resultados y retroceda al inicio.
  5. Intente hacer coincidir “filesaveasstring”. No hay partidos no visitados. Hecho.
  6. Seleccione lo más probable de [[archivo guardar como cadena] [archivos ave como cadena]] usando un analizador heurístico o en lenguaje natural.

Haz que la gente los resuelva como un captcha en tu sitio web 🙂

No conozco una biblioteca que haga esto, pero no es muy difícil escribir si tiene una lista de palabras:

 wordList = file('words.txt','r').read().split() words = set( s.lower() for s in wordList ) def splitString(s): found = [] def rec(stringLeft, wordsSoFar): if not stringLeft: found.append(wordsSoFar) for pos in xrange(1, len(stringLeft)+1): if stringLeft[:pos] in words: rec(stringLeft[pos:], wordsSoFar + [stringLeft[:pos]]) rec(s.lower(), []) return found 

Esto devolverá todas las formas posibles de dividir la cadena en las palabras dadas.

Ejemplo:

 >>> splitString('filesaveas') [['file', 'save', 'as'], ['files', 'ave', 'as']] 

Si no lo hace por diversión, pero en realidad está haciendo algo por trabajo, etc., mi consejo es abordar esto en la fuente. ¿Por qué tienes estas cadenas combinadas de esa manera? ¿De dónde sacaste esas cuerdas? Si es posible, inserte espacios en la fuente de donde provienen esas cadenas.

Sé que esta pregunta está marcada para Python pero necesitaba una implementación de JavaScript. Saliendo de las respuestas anteriores, pensé que compartiría mi código. Parece funcionar decentemente.

 function findWords(input){ input = input.toLowerCase().replace(/\s/g, ""); //Strip whitespace var index = 0; var validWords = []; for (var len = input.length; len > 0; len--){ //Go backwards as to favor longer words var testWord = input.substr(index, len); var dictIndex = _dictionary.indexOf(testWord.replace(/[^az\']/g, "")); //Remove non-letters if (dictIndex != -1){ validWords.push(testWord); if (len == input.length){ break; //We are complete } var nextWords = findWords(input.substr(len, input.length - len)); //Recurse if (!nextWords.words.length){ //No further valid words validWords.pop(); } validWords = validWords.concat(nextWords.words); if (nextWords.complete === true){ break; //Cascade complete } } } return { complete:len > 0, //We broke which indicates completion words:validWords }; } 

Nota: se espera que “_dictionary” sea un conjunto de palabras ordenadas por frecuencia. Estoy usando una lista de palabras del Proyecto Gutenberg.