2011-02-18 74 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部分。