Есть у меня пару функций, которые возвращают две строки
"Какие произведения писателей заставляются задуматься о великом?" --- Исходная строка "Какие произведение писателей заставляются о великом?" ---- Строка, которую вернула функция
Мне надо, чтобы в исходной строке подсвечивалось так
Какие произведения писателей заставляются задуматься о великом
Прошу помощи
javascript
var string1 = "Какие произведения писателей заставляются задуматься о великом?";
var string2 = "Какие произведение писателей заставляются о великом?";
var elem = document.querySelector("result");
html:
<p class="result"></p> <! -- Просто пустой абзац -->
Исходная строка может быть больше той, которая вернула функция, а может и не быть больше (ну вы поняли)
let string1 = "Какие произведения писателей заставляются задуматься о великом?";
let string2 = "Какие произведения писателей заставляются о великом?";
document.getElementById("result").innerHTML = textHighlight(string1, string2);
function textHighlight(str1, str2) {
str1 = str1.split(" ");
let str = str1.map(subStr => {
if (str2.includes(subStr)) {
return `<span class="highlight">${subStr}</span>`;
} else {
return subStr;
}
});
return str.join(" ");
}
.highlight {
color: red;
}
<p id="result"></p>
немного не в тему, но.
что-то вроде diff строк с применением Map
// --
const makeBold = (str) => `<b>${str}</b>`;
// разделить строку на массив слов
const split = (str) => str.split(' ');
// создать Map<string, boolean> из массива строк
const toMap = (arr) => new Map(Array.from(arr, str => [str, true]));
// --
const compare = (a, b) => {
let aM = toMap(split(a));
let bM = toMap(split(b));
// --
aM.forEach((val, key) => { bM.has(key) && bM.set(key, false); });
bM.forEach((val, key) => { aM.has(key) && aM.set(key, false); });
// --
return [
Array.from(aM, ([key, val]) => val ? makeBold(key) : key).join(' '),
Array.from(bM, ([key, val]) => val ? makeBold(key) : key).join(' '),
];
};
document.body.insertAdjacentHTML('beforeend', compare('Какие произведения писателей заставляют задуматься о великом', 'Какие произведения писателей заставляют о великом').join('<br>'));
document.body.insertAdjacentHTML('beforeend', '<hr>');
document.body.insertAdjacentHTML('beforeend', compare('Какие произведения писателей заставляют задуматься о великом', 'Какие произведения писател заставляют о великом').join('<br>'));
а там то же самое на TS
Последовательный поиск от последнего совпадения - это и логичнее, и (должно быть) быстрее проверки каждого слова через includes(word):
const str1 = 'Какие произведения писателей заставляют задуматься о великом?';
const str2 = 'Какие произведение писателей заставляют о великом?';
const elem = document.querySelector('.result');
elem.innerHTML = wrapMatches(str1, str2, '<span class="green">');
console.log(elem.innerHTML);
function wrapMatches(strA, strB, wrapper='<b>') {
const [wordsA, wordsB] = [strA.split(/\s+/), strB.split(/\s+/)].sort(
(a, b) => b.length - a.length
);
const [wordsAlc, wordsBlc] = [wordsA, wordsB].map(
arr => arr.map(itm => itm.toLowerCase())
);
const endTag = `</${wrapper.match(/^<([^\s>]+)/)[1]}>`,
len = wordsA.length,
result = [];
let open = false;
for (let lastMatchIdx = 0, i = 0; i < len; ++i) {
let matchIdx = wordsBlc.indexOf(wordsAlc[i], lastMatchIdx);
if (matchIdx !== -1) {
if (!open)
open = !!result.push(wrapper); // всегда вернет true: ="NOT(NOT(n)), n > 0"
lastMatchIdx = matchIdx;
} else if (open) {
open = !result.push(endTag); // всегда вернет false: ="NOT(n), n > 0"
}
result.push(wordsA[i]);
}
if (open)
result.push(endTag);
return result.join(' ');
}
p { font-family: sans-serif; }
.green { font-weight: bold; color: #4d4; }
<p class="result"></p>
Второй аргумент indexOf это начальный индекс поиска - передаем индекс последнего найденного слова (lastMatchIdx), и получаем короткий проход по массиву: даже в пессимистичном сценарии, будет проверено length - lastMatchIdx элементов (только часть массива, а не всегда все его элементы от начала до конца).
Плюс, indexOf с массивами сам по себе работает быстрее includes.
Плюс, сохраняется последовательность, поэтому не будет неожиданных результатов при строках вида 'aaa bbb ccc bbb', 'aaa ccc bbb'.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости