我有一个有趣的问题,我使用PHP的str_ireplace()
突出显示关键字数组中的文本。
假设这是我想从示例文本中突出显示的一组关键字或短语:
$keywords = array('eggs', 'green eggs');
这是我的示例文本:
$text = 'Green eggs and ham.';
以下是我如何突出显示文本:
$counter = 0;
foreach ($keywords as $keyword) {
$text = str_ireplace($keyword, '<span class="highlight_'.($counter%5).'">'.$keyword.'</span>', $text);
$counter++;
}
这样做的问题是green eggs
永远不会得到匹配,因为eggs
在文本中已经被替换为:
Green <span class="highlight_0">eggs</span> and ham.
也可能存在部分重叠的情况,例如:
$keywords = array('green eggs', 'eggs and');
解决这类问题的明智方法是什么?
反转顺序:
$keywords = array('green eggs', 'eggs');
最简单的方法是先处理最长的字符串,然后再处理较短的字符串。只要确保你不会在同一个字符串上加倍(如果重要的话)。
也许这不是最漂亮的解决方案,但您可以跟踪关键字出现的位置,然后找到它们重叠的位置,并调整您想要包含跨度标签的位置
$keywords = array('eggs', 'n eggs a', 'eggs and','green eg');
$text = 'Green eggs and ham.';
$counter = 0;
$idx_array = array();
$idx_array_last = array();
foreach ($keywords as $keyword) {
$idx_array_first[$counter] = stripos($text, $keyword);
$idx_array_last[$counter] = $idx_array_first[$counter] + strlen($keyword);
$counter++;
}
//combine the overlapping indices
for ($i=0; $i<$counter; $i++) {
for ($j=$counter-1; $j>=$i+1; $j--) {
if (($idx_array_first[$i] <= $idx_array_first[$j] && $idx_array_first[$j] <= $idx_array_last[$i])
|| ($idx_array_last[$i] >= $idx_array_last[$j] && $idx_array_first[$i] <= $idx_array_last[$j])
|| ($idx_array_first[$j] <= $idx_array_first[$i] && $idx_array_last[$i] <= $idx_array_last[$j])) {
$idx_array_first[$i] = min($idx_array_first[$i],$idx_array_first[$j]);
$idx_array_last[$i] = max($idx_array_last[$i],$idx_array_last[$j]);
$counter--;
unset($idx_array_first[$j],$idx_array_last[$j]);
}
}
}
array_multisort($idx_array_first,$idx_array_last); //sort so that span tags are inserted at last indices first
for ($i=$counter-1; $i>=0; $i--) {
//add span tags at locations of indices
$textnew = substr($text,0,$idx_array_first[$i]).'<span class="highlight_'.$i.'">';
$textnew .=substr($text,$idx_array_first[$i],$idx_array_first[$i]+$idx_array_last[$i]);
$textnew .='</span>'.substr($text,$idx_array_last[$i]);
$text = $textnew;
}
输出为
<span class="highlight_0">Green eggs and</span> ham.