【问题标题】:Javascript / jQuery Find Text duplicatesJavascript / jQuery 查找文本重复项
【发布时间】:2011-02-18 20:21:35
【问题描述】:

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

【问题讨论】:

  • 比方说。 <body><p>....text.......</p></body>

标签: javascript jquery text duplicates


【解决方案1】:

有趣的问题——这是我可能会如何做的一个想法: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

我的 regex-fu 很弱,但是这个(相当混乱!)版本似乎可以正常工作:http://jsfiddle.net/YQdk5/2/ - 我很确定可能有更好的方法来做到这一点,但现在我有别管它! :D — 祝你好运!

更新 3

想一想,我不认为上次更新的代码有什么好处。这就是我删除它的原因。你仍然可以在这里找到它:http://jsfiddle.net/YQdk5/2/ 要点是使用正则表达式来匹配单词,类似于:

/^word(\.?)$/

【讨论】:

  • +1 的努力。我有一个类似的概念来查找重复的单词。句子是这里的问题。在您的情况下,它必须以点结尾才能被识别。因此,如果我们在不同的区域有相同的 2 个句子,但一个如果后面没有点,则不会被识别。
  • 我猜它更像是一个单词序列而不是一个句子,不是吗;)。
  • 是的。寻找解决此问题的想法和最佳方法。
  • 感谢您的努力,好方法。我喜欢你在第三次更新中所做的,虽然我可以改进,但总体来说是一个好的开始。
【解决方案2】:

这是使用后缀树的解决方案:

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)删除其他句子中包含的句子(即删除作为“this is a”一部分的“is”)。

您可以更改正则表达式以考虑 html 标记。

希望对你有帮助。

附: h 是找到重复项的回调。

【讨论】:

    【解决方案3】:

    你的 javascript 包含对名为 jQuery 的 javascript 库的引用。

    你没有在你的 HTML 中包含这个,因此它会失败。 您可以通过jquery cdn 包含它

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

    【讨论】:

      猜你喜欢
      • 2013-07-31
      • 1970-01-01
      • 1970-01-01
      • 2010-10-25
      • 2012-06-20
      • 1970-01-01
      • 2021-07-12
      • 2011-07-07
      • 2019-01-02
      相关资源
      最近更新 更多