У меня есть небольшая поисковая система, делающая свое дело, и хочу выделить результаты. Я думал, что все это сработало до тех пор, пока набор ключевых слов, которые я использовал сегодня, не выдул его из воды.ключевое слово highlight выделяет основные моменты в PHP preg_replace()
Проблема заключается в том, что preg_replace() выполняет цикл по замене, а в дальнейшем замены заменяют текст, который я вставлял в предыдущие. Смущенный? Вот моя псевдо функция:
public function highlightKeywords ($data, $keywords = array()) {
$find = array();
$replace = array();
$begin = "<span class=\"keywordHighlight\">";
$end = "</span>";
foreach ($keywords as $kw) {
$find[] = '/' . str_replace("/", "\/", $kw) . '/iu';
$replace[] = $begin . "\$0" . $end;
}
return preg_replace($find, $replace, $data);
}
КИ, так что он работает при поиске «Фред» и «Дагг» но, к сожалению, при поиске «класс» и «Lass» и «как» это наносит реальный вопрос при выделении «Class Group Джозефа»
Joseph's <span class="keywordHighlight">Cl</span><span <span c<span <span class="keywordHighlight">cl</span>ass="keywordHighlight">lass</span>="keywordHighlight">c<span <span class="keywordHighlight">cl</span>ass="keywordHighlight">lass</span></span>="keywordHighlight">ass</span> Group
Как бы я получить последние замены для работы только на не-HTML компонентах, а также позволяет маркировать весь матч? например если бы я искал «cla» и «lass», я бы хотел, чтобы «класс» был полностью выделен, поскольку в нем присутствуют как условия поиска, даже если они перекрываются, а выделение, которое было применено к первому совпадению, имеет класс "в нем, но , что не следует выделять.
Вздох.
Я предпочел бы использовать PHP-решение, чем jQuery (или любой клиентский).
Примечание: Я попытался отсортировать ключевые слова по длине, сначала сделав длинные, но это означает, что поиск по пересечению не выделяется, что означает «cla» и «lass» только часть слова «class» «выделил бы, и он все же убил заменяющие метки :(
EDIT: Я испортил, начиная с карандаша & бумаги и диких блужданий, и придумал очень неглазурованный код, чтобы решить эту проблему. , поэтому предложения по отделке/ускорению этого по-прежнему будут по достоинству оценены :)
public function highlightKeywords ($data, $keywords = array()) {
$find = array();
$replace = array();
$begin = "<span class=\"keywordHighlight\">";
$end = "</span>";
$hits = array();
foreach ($keywords as $kw) {
$offset = 0;
while (($pos = stripos($data, $kw, $offset)) !== false) {
$hits[] = array($pos, $pos + strlen($kw));
$offset = $pos + 1;
}
}
if ($hits) {
usort($hits, function($a, $b) {
if ($a[0] == $b[0]) {
return 0;
}
return ($a[0] < $b[0]) ? -1 : 1;
});
$thisthat = array(0 => $begin, 1 => $end);
for ($i = 0; $i < count($hits); $i++) {
foreach ($thisthat as $key => $val) {
$pos = $hits[$i][$key];
$data = substr($data, 0, $pos) . $val . substr($data, $pos);
for ($j = 0; $j < count($hits); $j++) {
if ($hits[$j][0] >= $pos) {
$hits[$j][0] += strlen($val);
}
if ($hits[$j][1] >= $pos) {
$hits[$j][1] += strlen($val);
}
}
}
}
}
return $data;
}
'$ hits [$ i] [0]' означает, что даны 0 '$ hits'? О, этот мой ум ... – Cyclone
'$ hits [$ i] [0]' является начальной точкой ключевого слова, а '$ hits [$ i] [1]' является конечной точкой. Это менее запутанно на бумаге :) – CrazyChris
Прочтите мой снова, заменив '$' на 'S' мысленно ... просто плохая шутка, я боюсь – Cyclone