2010-02-12 20 views
6

necesito encontrar algunas palabras o un patrón que coincida con un Javascript.Javascript string matching pattern help

este es el requisito.

tengo una cadena como esta,

aquí hay una guía rápida para la próxima vez que llegue a su aceite favorito y algunos otros temas

y necesito para que coincida con esta cadena contra una cadena como esta

favorite oil and some other topics can be based on something blah blah 

¿cómo obtengo la intersección de los bloques de texto coincidentes?

Ya he intentado interceptar la función de script de Javascript, para algunas cadenas no está funcionando correctamente.

¿Cómo solucionar este problema? ¿Esto se puede hacer usando Regex?

Por favor consejo.

Respuesta

8

Tienes que encontrar el Longest common substring.

Si las cadenas no son muy largas, recomiendo usar el enfoque de Tim. De lo contrario, se trata de una implementación de JavaScript del algoritmo de subcadena común más largo con programación dinámica. El tiempo de ejecución es O (mn) donde m y n son las longitudes de las 2 cuerdas, respectivamente.

Un ejemplo de uso:

var first = "Here is a quick guide for the next time you reach for your favorite oil and some other topics"; 
var second = "favorite oil and some other topics can be based on something blah blah"; 

console.log(first.intersection(second)); // ["favorite oil and some other topic"] 

Ésta es la implementación del algoritmo. Devuelve una matriz de la subcadena (s) común más larga. Extendió la clase de cadena nativa, por lo que el método de intersección está disponible en todas las cadenas.

String.prototype.intersection = function(anotherString) { 
    var grid = createGrid(this.length, anotherString.length); 
    var longestSoFar = 0; 
    var matches = []; 

    for(var i = 0; i < this.length; i++) { 
     for(var j = 0; j < anotherString.length; j++) { 
      if(this.charAt(i) == anotherString.charAt(j)) { 
       if(i == 0 || j == 0) { 
        grid[i][j] = 1; 
       } 
       else { 
        grid[i][j] = grid[i-1][j-1] + 1; 
       } 
       if(grid[i][j] > longestSoFar) { 
        longestSoFar = grid[i][j]; 
        matches = []; 
       } 
       if(grid[i][j] == longestSoFar) { 
        var match = this.substring(i - longestSoFar + 1, i); 
        matches.push(match); 
       } 
      } 
     } 
    } 
    return matches; 
} 

también necesitan esta función auxiliar para crear una matriz 2D con todos los elementos inicializan a 0.

// create a 2d array 
function createGrid(rows, columns) { 
    var grid = new Array(rows); 
    for(var i = 0; i < rows; i++) { 
     grid[i] = new Array(columns); 
     for(var j = 0; j < columns; j++) { 
      grid[i][j] = 0; 
     } 
    } 
    return grid; 
} 
+0

Buena respuesta. Había considerado implementarlo yo mismo, pero tenía trabajo por hacer. –

+0

Anurag, muchas gracias. ¡funciona maravillosamente! – kakopappa

+0

@Aruna - me alegro de que funcionó para ti. @Tim - es rápido pero carece de simplicidad.hay otro algoritmo que usa árboles de sufijo y toma O (n + m) pero no hoy :) – Anurag

3

Esto no es muy eficiente y hay mucho mejores maneras de hacer esto en general (ver @ respuesta de Anurag), pero es simple y funciona bien para cadenas cortas:

function stringIntersection(str1, str2) { 
    var strTemp; 

    // Swap parameters if necessary to ensure str1 is the shorter 
    if (str1.length > str2.length) { 
     strTemp = str1; 
     str1 = str2; 
     str2 = strTemp; 
    } 

    // Start with the whole of str1 and try shorter substrings until 
    // we have a common one 
    var str1Len = str1.length, l = str1Len, start, substring; 
    while (l > 0) { 
     start = str1Len - l; 
     while (start >= 0) { 
      substring = str1.slice(start, l); 
      if (str2.indexOf(substring) > -1) { 
       return substring; 
      } 
      start--; 
     } 
     l--; 
    } 
    return ""; 
} 

var s1 = "Here is a quick guide for the next time you reach" 
     + " for your favorite oil and some other topics"; 
var s2 = "favorite oil and some other topics can be based on" 
     + " something blah blah"; 

alert(stringIntersection(s1, s2)); 
+0

Hola Tim. gracias por su esfuerzo y tiempo! .. apreciado – kakopappa

0

un simple polyfill de filtro de una cadena

if (!String.prototype.intersection) { 
    String.prototype.intersection = function(anotherString, caseInsensitive = false) { 
    const value = (caseInsensitive) ? this.toLowerCase()   : this; 
    const comp = (caseInsensitive) ? anotherString.toLowerCase() : anotherString; 
    const ruleArray = comp.split("").reduce((m,v) => {m[v]=true; return m;} ,{}) 
    return this.split("").filter((c, i) => ruleArray[value[i]]).join("") 
    } 
} 

"HelloWorld" .intersection ("HEWOLRLLODo", true)

"HelloWorld" - caso insensible

"HelloWorld" .intersection ("HEWOLRLLODo")

"HOWO" - caso sensible