【问题标题】:Wrap sub-string with <span> tag (with nesting)用 <span> 标签包裹子字符串(带有嵌套)
【发布时间】:2017-06-26 04:41:11
【问题描述】:

我有一个函数可以根据搜索子字符串用 标记包装给定字符串的一部分。

例如:

“然后是第一颗流星的夜晚。”

它会返回(没关系):

“然后是第一个流星的夜晚”。

“first of” 搜索字符串。如果我们尝试搜索字符串 "first of rs"(注意 "rs" 包含在 "fiRSt" 已经存在于我们的搜索字符串中),现在它给出:

“然后是first流星的夜晚 ”。

但我们想看到的是第一个结果:

“然后是第一个流星的夜晚”。

const markSubstring = (string, searchString) => {

    _.forEach(searchString.split(' '), function(value){
        if(value != '') {
            let regEx = new RegExp('(' + value + ')', "ig");
            string = string.replace(regEx, '<span>$1</span>');
        }
    });

    return _.map(string.split(/(<span>.*?<\/span>)/), (item, key) => {
        let val = item.split(/<span>(.*?)<\/span>/);
        if (val.length == 3) { return `<span>${val[1]}</span>` }
        return `${val}`;
    });
};

console.log(markSubstring('Then came the night of the first falling star.', 'first of'));
console.log('---------');
console.log(markSubstring('Then came the night of the first falling star.', 'first of rs'));
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"&gt;&lt;/script&gt;

修改函数以获得预期结果的最佳方法是什么?

更新

给定字符串:然后是第一颗流星的夜晚。

一些搜索查询及其预期结果:

来了 -> 然后(来了)第一颗流星的夜晚。

先来 -> 然后(来)(第一颗)流星之夜。

am ig first -> 然后 c(am)e 是(第一颗)流星的 n(ig)ht。

first rs -> 然后是(第一颗)流星之夜。

first rs am -> 然后 c(am)e 在(第一颗)流星之夜。

等等

所以我们将搜索字符串除以空格,并尝试在给定的字符串中找到这些“子搜索查询”。

使用new RegExp('(' + value + ')', "ig");,当搜索嵌套时,我们有一个 显示为字符串中的文本(不仅仅是它具有的样式)。所以我想最好的选择是不要在单词(或其部分已经突出显示)时放置它。

【问题讨论】:

    标签: javascript regex search replace substring


    【解决方案1】:

    编辑

    好的,我添加了以下逻辑来完善它。

    1. 按长度对所有搜索词进行排序,以便首先搜索最长的词。这样,如果搜索了一个较短的词,但它已经包含在较长的词中(已用&lt;span&gt; 包裹),我们就知道不要插入另一个跨度。
    2. 我们从字符串中拆分出每个单词,并确保它没有被 &lt;span&gt; 包裹

    您可以通过确保每个单词都是完整的单词而不是另一个单词的一部分来修复它。

    例如,如果我们使用正则表达式模式:/(^|\s)(first)(\s|$)/gi 我们确保单词first 后面必须跟一个空格、字符串的开头或结尾。因此,在这种情况下,单词rs 不能被视为单词。

    查看实际操作:

    const markSubstring = (string, searchString) => {
        var searchStrings = searchString.split(' ').sort(function(a, b){return b.length - a.length;});
        
        _.forEach(searchStrings, function(value){
            if(value != '') {
                let regEx = new RegExp('(' + value + ')', "ig");
                let validationRegEx = new RegExp('<span>.*?(' + value + ').*?<\/span>', "ig");
                var words = [];
                _.forEach(string.split(' '), function(word) {
                  if (!word.match(validationRegEx)) {
                    word = word.replace(regEx, '<span>$1</span>');
                  }
                  words.push(word);
                })          
                string = words.join(' ');
            }
        });
    
        return _.map(string.split(/(<span>.*?<\/span>)/), (item, key) => {
            let val = item.split(/<span>(.*?)<\/span>/);
            if (val.length == 3) { return `<span>${val[1]}</span>` }
            return `${val}`;
        });
    };
    
    console.log(markSubstring('Then came the night of the first falling star.', 'first of'));
    console.log('---------');
    console.log(markSubstring('Then came the night of the first falling star.', 'first of rs'));
    console.log('---------');
    console.log(markSubstring('Then came the night of the first falling star. rs is also a word.', 'first of rs'));
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 想出了基本相同的解决方案,但直到我注意到我完全忘记了双反斜杠的事情,它才起作用
    • 感谢您的快速回复!好的,它解决了嵌套问题,但现在它只适用于完整的单词(末尾有空格,没有逗号或点)。我不擅长正则表达式。我们如何将这两种行为结合起来,以便能够在同一字符串中找到例如“bla bla first bla bla”中的“rs”和“first rs”(正确的方式)?
    • 如果字符串的一部分还没有被 span 包裹,您想突出显示该字符串的一部分吗?
    • 我希望得到一个字符串,其中突出显示(包装)的部分是搜索字符串的一部分(搜索字符串除以要应用于给定字符串的空格)。请稍等,我将更新一个问题。
    • @Max 好的,现在就去看看
    猜你喜欢
    • 2013-09-03
    • 1970-01-01
    • 2022-11-21
    • 2013-05-09
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多