在字符串中查找并从匹配字符串的列表中查找并替换为html标签

时间:2019-01-24 15:02:22

标签: javascript html reactjs

对此我有些困惑,但我想实现以下目标。

我有一个大字符串,在该字符串内,我想与字符串数组匹配并用标记标签替换。

采用以下字符串:

The quick brown fox jumps over a lazy dog.

这是我希望与正文匹配的字符串列表(可能是整个句子,而不仅仅是一个单词):

['quick', 'brown', 'lazy dog', '.']

我要达到的结果:

// ['The', <span>quick</span>, '<span>brown</span>', 'fox jumps over a' '<span>lazy dog</span>', '<span>.</span>]

注意事项和其他说明:

  • 避免使用诸如addClass,innerHTML,appendChild之类的DOM操作,因为我想在React组件的渲染功能中提出一种优雅的解决方案
  • 不要使用完整的字符串正则表达式解决方案,因为我想插入react DOM元素,而不是在解决方案之后操作和解析dom
  • 我想将其他信息附加到span标签IE上,即react DOM元素通过这些包装的字符串进行过滤,例如ID或对该元素的本机react事件
  • 我必须迎合匹配的句子,而不仅仅是单个单词。
  • 没有浏览器要求
  • 字符串列表将始终是唯一的并且没有重叠
  • 列表中并非所有字符串都在文本(;)内)

Kinda我要处理的数据集: https://codepen.io/nigel_manny/pen/omjxrx

祝你好运,谢谢你!

4 个答案:

答案 0 :(得分:2)

我认为这里的诀窍是分割和征服字符串,查找并包装与HTML元素匹配的单词/句子,并对每个单词/句子重复该过程。

演练:

// Sample data
const str = "The quick brown fox jumps over a lazy dog.";
const words = ["quick", "brown", "lazy dog", ".", "missing word"];

让我们将str放入数组中,并将str放在数组的唯一元素中。

// Start
["The quick brown fox jumps over a lazy dog."]

// Iteration 1: replace all "quick" with span
// When matched, we split current element into three array elements
// Before match part + matched part + after match part
["The ", <span>quick</span>, " brown fox jumps over a lazy dog."]

// Iteration 2: replace all "brown" with span
["The ", <span>quick</span>, " ", <span>brown</span>, " fox jumps over a lazy dog."]

// Iteration 3: replace all "lazy dog" with span
["The ", <span>quick</span>, " ", <span>brown</span>, " fox jumps over a ", <span>lazy dog</span>, "."]

// Iteration 4: replace all "." with span
["The ", <span>quick</span>, " ", <span>brown</span>, " fox jumps over a ", <span>lazy dog</span>, "", <span>.</span>, ""]

// Iteration 5: replace all "missing word" with span, but this sentence doesn't exist, so output will remain same
["The ", <span>quick</span>, " ", <span>brown</span>, " fox jumps over a ", <span>lazy dog</span>, "", <span>.</span>, ""]

这是可行的解决方案

Edit 8nkp163270

答案 1 :(得分:1)

我的提案(包含更新的数据)为(不再有正则表达式):

const text = 'Could it be improved where an ai suggests text books and notes which could help with a question (maybe based on keywords?) and then at the end the user rates the helpfulness of the suggestions, which helps the ai learn what to suggest. Taking lead from Medium articles, it would be awesome to be able to highlight text and it gives you suggestions of what to do with it (copy to clipboard, bookmark to my account etc) and also show me the most highlighted sections of each set of notes so i see what the community is finding most useful. I think linking to buy the paper version of the book is a weak and half hearted way to monitise this idea - why not go "full netflix" and get rid of the blockbusters model altogether. Scrap all the print titles and charge a subscription to be able to be able to access the extra revision information. In a Spotify freemium kind of way you could access the question banks for free but to get the revision notes/books etc you would pay. You would need a subscription model which worked for the amount of time someone is likely to find this information useful. Maybe micropayments solution would be better than a subscription?';

const matchingSentences = [
    'Could it be improved where an ai suggests text books and notes which could help with a question (maybe based on keywords?) and then at the end the user rates the helpfulness of the suggestions, which helps the ai learn what to suggest.',
    'Taking lead from Medium articles, it would be awesome to be able to highlight text and it gives you suggestions of what to do with it (copy to clipboard, bookmark to my account etc) and also show me the most highlighted sections of each set of notes so i see what the community is finding most useful.',
    'I think linking to buy the paper version of the book is a weak and half hearted way to monitise this idea - why not go "full netflix" and get rid of the blockbusters model altogether.',
    'Scrap all the print titles and charge a subscription to be able to be able to access the extra revision information.'
];

var result = [];
var startingIdx = 0;

matchingSentences.forEach(function(e, i) {
    var idx = text.indexOf(e);
    if (idx != -1) {
        if (idx != startingIdx) {
            result.push(text.substr(startingIdx, e.length));
        }
        var str = '<span>' + e + '</span>';
        result.push(str);
        startingIdx += (e.length + 1);
    }
});
if (startingIdx < text.length) {
    result.push(text.substr(startingIdx));
}

console.log(result);

答案 2 :(得分:0)

您可以拆分字符串,然后将每个单词与列表元素匹配,并将它们存储在单独的列表中。

您的代码可能看起来像这样。

const stringText = 'The quick brown fox jumps over a lazy dog.';
const matchList = ['quick', 'brown', 'lazy', '.'];
const splittedText = stringText.replace('.', ' .').split(' ');
const matchedSplittedText = splittedText.map(word => matchList.includes(word) ? handleWord(word) : word);

答案 3 :(得分:0)

命令式和幼稚式的方法是循环遍历数组中的每个单词并检查句子中的出现:

const string = "The quick brown fox jumps over a lazy dog. A full sentence.";
const replaceWords = ['quick', 'brown', 'lazy', '.', 'A full sentence.'];
const stringAsArray = string.replace('.', ' .').split(' ');

const splittedReplaceWords = replaceWords.flatMap(word => word.replace('.', ' .').split(' '));

const jsxEnhancedText = splittedReplaceWords.map(word => {
    if(stringAsArray.indexOf(word) > -1) {
        return React.createElement('span', props, word);
    }

    return word;
})

React.createElement只是非JSX变体。 React.createElement('span', props, word)将元素作为第一个参数(例如'span'或自定义参数),props将数组作为第二个参数,然后将子元素(在本例中为单词)。有关更多信息,请参见https://reactjs.org/docs/react-api.html#createelement