2011-02-18 25 views
7

你会如何接近在一个文本文件发现重复。重复可以是一组连续的单词或句子。句子不必以点结尾。假设页面包含一个200行的文档,其中2个句子是相同的,我们希望在单击“检查重复按钮”时将这2个句子突出显示为重复项。的Javascript/jQuery的查找文本复制

+0

你的html结构如何? – 2011-02-18 20:34:28

+0

让我们说。 `

....文字.......

` – Hussein 2011-02-18 20:56:20

回答

5

有趣的问题 - 这里是我如何会做大概的想法:http://jsfiddle.net/SaQAs/1/ - 不无论如何优化!

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; 
}); 

更新1

这一个发现的相同的序列的话:http://jsfiddle.net/YQdk5/1/从这里它不应该是很难例如比较时,忽略碎片尾部的任何标点符号 - 您只需编写自己的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(' ')); 

更新2

我的正则表达式福弱,但是这(相当混乱!)版本似乎好工作:http://jsfiddle.net/YQdk5/2/ - 我敢肯定,有可能是一个更好的方式这样做,但现在我必须离开它! :D - 祝你好运!

更新3

关于它的思考,我不认为从以前更新的代码是什么好。这就是我删除它的原因。你仍然可以在这里找到它:http://jsfiddle.net/YQdk5/2/ 主要的一点是要使用正则表达式来匹配的话,沿着线的东西:

/^word(\.?)$/ 
3

下面是一个使用后缀树的解决方案:

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)将输入文本拆分为单词数组。 2)建立后缀树。 3)找到树的最长后缀。 4)删除其他句子中包含的句子(即删除“is”是“this is a”的一部分)。

您可以更改正则表达式来考虑HTML标签。

我希望这可以帮助你。

P.S. h是找到重复项的回调。

0

你的JavaScript包含一个名为jQuery的JavaScript库的引用。

你不包括在你的HTML中,因此它会失败。 您可以通过jquery cdn

包括它今天提示:使用浏览器中的开发人员工具。在控制台中,您可以看到失败的JavaScript部分。