2011-02-18 14 views
7

¿Cómo se acercaría a encontrar duplicados en un documento de texto? Los duplicados pueden ser un conjunto de palabras o frases consecutivas. La oración no es necesaria y termina con un punto. digamos que la página contiene un documento de 200 líneas de las cuales 2 oraciones son idénticas, queremos resaltar esas 2 oraciones como duplicadas cuando se hace clic en "verificar botón duplicado".Javascript/jQuery Buscar texto duplicado

+0

¿Cómo se estructura su html? –

+0

Digamos. '

.... texto .......

' – Hussein

Respuesta

5

Pregunta interesante: esta es una idea de cómo lo haría probablemente: http://jsfiddle.net/SaQAs/1/ - ¡No se ha optimizado de ninguna manera!

var text = $('p').text(), 
    words = text.split(' '), 
    sortedWords = words.slice(0).sort(), 
    duplicateWords = [], 
    sentences = text.split('.'), 
    sortedSentences = sentences.slice(0).sort(), 
    duplicateSentences = []; 


for (var i=0; i<sortedWords.length-1; i++) { 
    if (sortedWords[i+1] == sortedWords[i]) { 
     duplicateWords.push(sortedWords[i]); 
    } 
} 
duplicateWords = $.unique(duplicateWords); 

for (var i=0; i<sortedSentences.length-1; i++) { 
    if (sortedSentences[i+1] == sortedSentences[i]) { 
     duplicateSentences.push(sortedSentences[i]); 
    } 
} 
duplicateSentences = $.unique(duplicateSentences); 

$('a.words').click(function(){ 
    var highlighted = $.map(words, function(word){ 
     if ($.inArray(word, duplicateWords) > -1) 
      return '<span class="duplicate">' + word + '</span>'; 
     else return word; 
    }); 
    $('p').html(highlighted.join(' ')); 
    return false; 
}); 

$('a.sentences').click(function(){ 
    var highlighted = $.map(sentences, function(sentence){ 
     if ($.inArray(sentence, duplicateSentences) > -1) 
      return '<span class="duplicate">' + sentence + '</span>'; 
     else return sentence; 
    }); 
    $('p').html(highlighted.join('.')); 
    return false; 
}); 

Actualización 1

Ésta encuentra secuencias de palabras idénticas: http://jsfiddle.net/YQdk5/1/ A partir de aquí, no debería ser difícil, por ejemplo, ignore cualquier tipo de puntuación al final de los fragmentos al comparar: solo tendría que escribir su propia versión de un método inArray.

var text = $('p').text(), 
    words = text.split(' '), 
    sortedWords = words.slice(0).sort(), 
    duplicateWords = [] 
    highlighted = []; 

for (var i=0; i<sortedWords.length-1; i++) { 
    if (sortedWords[i+1] == sortedWords[i]) { 
     duplicateWords.push(sortedWords[i]); 
    } 
} 
duplicateWords = $.unique(duplicateWords); 

for (var j=0, m=[]; j<words.length; j++) { 
    m.push($.inArray(words[j], duplicateWords) > -1); 
    if (!m[j] && m[j-1]) 
     highlighted.push('</span>'); 
    else if (m[j] && !m[j-1]) 
     highlighted.push('<span class="duplicate">'); 
    highlighted.push(words[j]); 
} 

$('p').html(highlighted.join(' ')); 

Actualización 2

Mi expresión regular-fu es débil, pero esta versión parece funcionar bien (muy sucio!): http://jsfiddle.net/YQdk5/2/ - Estoy bastante seguro de que podría haber una mejor manera de haciendo esto, ¡pero por ahora tengo que dejarlo solo! : D - ¡Buena suerte!

Actualización 3

Pensando en ello, no creo que el código de la actualización anterior es nada bueno. Es por eso que lo eliminé. Todavía se puede encontrar aquí: http://jsfiddle.net/YQdk5/2/ El punto principal es usar una expresión regular para que coincida con las palabras, algo a lo largo de las líneas de:

/^word(\.?)$/ 
+0

eso es bastante limpio. –

+0

+1 por los esfuerzos. Tenía un concepto similar para encontrar palabras duplicadas. La oración es el problema aquí. En su caso, debe terminar con un punto para que sea reconocido. Entonces, si tenemos las mismas 2 oraciones en diferentes áreas, pero una si no está seguida por un punto, no será reconocida. – Hussein

+0

Supongo que es más una secuencia de palabras que una oración, ¿verdad?). – polarblau

3

Aquí está la solución que utiliza el sufijo árbol:

function SuffixTree(text) { 
    var regex = /\b\w+/g; 
    var words = text.match(regex); 
    var wave = []; 
    var words_l = words.length; 
    if (words_l == 0) return false; 
    this.tree = this.node("", false); 
    for (var i = 0; i < words_l; ++i) { 
     var x = words[i] + "_"; 
     wave.push(this.tree); 
     var wave_l = wave.length; 
     for (var j = 0; j < wave_l; ++j) { 
      var y = wave[j]; 
      if (typeof y[x] != 'undefined') y[x].count++; 
      else y[x] = this.node(words[i], y); 
      wave[j] = y[x]; 
     } 
    } 
} 

SuffixTree.prototype = { 
    dummy: {count: 1}, 

    node: function(word, num, parent) { 
     return { 
      count: 1, 
      word: word, 
      parent: parent 
     }; 
    }, 

    duplicates: function(h) { 
     this.dups = []; 
     this.bypass(this.tree, h, 0); 
     var l = this.dups.length; 
     this.dups.sort(function(d1, d2) { return d1.depth > d2.depth ? 1 : -1; }); 
     for (var i = 0; i < l; ++i) { 
      var d = this.dups[i]; 
      this.dups[i] = { s: " " + this.sentence(d.a) + " ", depth: d.depth, count: d.a.count }; 
     } 
     for (var i = 0; i < l; ++i) { 
      var d = this.dups[i]; 
      console.log(i, d.s); 
     } 
     for (var i = 0; i < l; ++i) { 
      var d = this.dups[i]; 
      var fl = true; 
      for (var j = i + 1; j < l; ++j) { 
       if (this.dups[j].s.indexOf(d.s) != -1) fl = false; 
      } 
      if (fl) h(d.s.substr(1, d.s.length - 2), d.count); 
     } 
    }, 

    bypass: function(a, h, depth) { 
     if (a.constructor != Object) return; 
     var fl = true; 
     for (var i in a) { 
      if (i == 'parent') continue; 
      var b = a[i]; 
      if (b.count == a.count) fl = false; 
      this.bypass(b, h, depth + 1); 
     } 
     if (fl && a.count > 1) { 
      this.dups.push({ a: a, depth: depth }); 
     } 
    }, 

    sentence: function(a) { 
     var s = a.word; 
     while (a = a.parent) { 
      s = a.word + " " + s; 
     } 
     return s; 
    } 
}; 

var text = "This is a text with some duplicates: words, sentences of different length. For example here is a duplicate word. This sentence has some duplicates. But not all of us can find clones."; 

var T = new SuffixTree(text); 
var h = function(s, c) { 
    document.write(s + "[" + c + "]<br/>"); 
}; 
T.duplicates(h); 

1) Divida el texto de entrada en la matriz de palabras. 2) Construye el árbol de sufijos. 3) Encuentra los sufijos más largos del árbol. 4) Eliminar oraciones que están contenidas en otros (es decir, eliminar "es" que es una parte de "esto es un").

Puede cambiar la expresión regular para tener en cuenta las etiquetas html.

Espero que esto te ayude.

P.S. h es la devolución de llamada para duplicados encontrados.

0

Estás javascript contiene referencias a una biblioteca de JavaScript llamada jQuery.

Usted no está incluyendo esto en su HTML, y por lo tanto fallará. Puede incluirlo a través de jquery cdn

Y consejo de hoy: Use las herramientas de desarrollador en su navegador. En la consola, puede ver qué partes de javascript fallan.