Есть у меня пару функций, которые возвращают две строки
"Какие произведения писателей заставляются задуматься о великом?" --- Исходная строка "Какие произведение писателей заставляются о великом?" ---- Строка, которую вернула функция
Мне надо, чтобы в исходной строке подсвечивалось так
Какие произведения писателей заставляются задуматься о великом
Прошу помощи
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'
.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Почему при объявлении стандартных библиотек компилятор принимает запись #include <syslib>, а стоит подключить свою библиотеку, например, вида...
Даже с стилем WS_POPUP остаются эти мерзкие кнопки и заголовок с названием окна, мне нужно и то и другое убрать(желательно без использования WS_POPUP)