En realidad, hay un acceso directo a una muy buena aproximación. Desafortunadamente, no recuerdo a quién acreditar, pero vi esto mencionado en una discusión similar y pensé que era una buena solución.
Divida su consulta en caracteres, únalos con un comodín regex y luego ejecute la expresión regular en su conjunto de cadenas.
# python for string in strings_to_search: if re.search(".*?".join(query), string): pick(string)
O si te gusta el golf …
- Cómo reducir la programación dinámica a programación lineal
- ¿Qué estructuras de datos y algoritmos básicos se deben aprender antes de comenzar la programación competitiva?
- ¿Qué es la notación O grande? ¿Y deberían saberlo los programadores principiantes?
- ¿Cuál es el mejor algoritmo de reconocimiento de patrones hoy?
- En un microprocesador 8085, ¿cómo podemos encontrar el número de ciclos de la máquina y el número de estados T de cualquier mnemónico dado?
matches = [s for s in strings_to_search if re.search(".*?".join(query), s)]
Si deshabilita el rastreo, una búsqueda en n cadenas con longitud de consulta k debería ejecutarse en tiempo O (nk) (tal vez dependiendo del motor de expresiones regulares).
Eso no ayuda a resaltar las coincidencias, pero para eso puedes:
- observe que la coincidencia de expresiones regulares es determinista, por lo que regex-replace en el conjunto de resultados para insertar algún formato;
- o escriba un analizador de expresiones regulares muy simple para hacer cosas personalizadas. Dado que los únicos operadores son los
.
y*
, puede hacerlo con un DFA.
En realidad, tengamos ese analizador personalizado. (Demostración en vivo aquí).
// I've neither proven this correct nor tested it extensively. Beware. // ...but at least it's in JavaScript? function fuzzyMatch(searchSet, query) { var tokens = query.toLowerCase().split(''), matches = []; searchSet.forEach(function(string) { var tokenIndex = 0, stringIndex = 0, matchWithHighlights = '', matchedPositions = []; string = string.toLowerCase(); while (stringIndex = tokens.length) { matches.push({ match: string, highlighted: matchWithHighlights + string.slice( stringIndex + 1 ), // Maybe use this to weight matches? // More consecutive numbers = higher score? positions: matchedPositions }); break; } } else { matchWithHighlights += string[stringIndex]; } stringIndex++; } }); return matches; } function highlight(string) { return '' + string + ''; }