Yesterday I hurriedly finished solving a user’s problem and uploaded the rough answer. I am convinced there must be a more elegant solution to handle $sColor than the following:
// associate color with search word
foreach( $aSrchs as $id => $sSrc):
$x[$sSrc] = $aClrs[$id];
$y[ $aClrs[$id] ] = $sSrc;
endforeach;
// fred($x, '$x');
// step through $aWords
$aResult = [];
foreach( $aWords as $word ): // Say ye to the righteous
if( $i2=in_array($word, $y) ):
$sColor = $x[ $word ]; // integer
$aResult[] = '<b style="color:' .$sColor .';">' .$word .'</b>';
else:
$aResult[] = $word;
endif;
endforeach;
Complete solution can be found here:
Online Demo
I would be grateful for more succinct solutions.
Edit
iPad mini 2 rendering is horrible and will rectify when back on the desktop.
1 Like
This is my stab at it. It recycles the colors that is assigned to the words when the number of matched words is greater than the colors available.
<?php
function highlight($text, array $words, array $colors, $ignoreCase = false, $format = '<b style="color:%s">%s</b>')
{
$wordToColor = [];
$colorIdx = 0;
$re = '~\\b('.implode('|', $words).')\\b~';
if ($ignoreCase) {
$re .= 'i';
}
return preg_replace_callback($re, function ($m) use ($colors, $format, &$wordToColor, &$colorIdx) {
$word = $m[0];
if (!isset($wordToColor[$word])) {
$wordToColor[$word] = $colors[$colorIdx];
}
$colorIdx = $colorIdx < count($colors) - 1 ? $colorIdx + 1 : 0;
$color = $wordToColor[$word];
return sprintf($format, $color, $word);
}, $text);
}
$text = "I've seen things you people wouldn't believe. Attack ships on fire off the shoulder of Orion. I watched C-beams glitter in the dark near the Tannhäuser Gate. All those moments will be lost in time, like tears...in...rain. Time to die.";
$words = ['tannhäuser', 'orion', 'fire', 'tears', 'rain' ,'die'];
$colors = ['red', 'green', 'blue'];
$format = '<span style="color:%s;">%s</span>';
$hl = highlight($text, $words, $colors, true, $format);
echo <<< EOF_HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Highlight</title>
</head>
<body>
<p>$hl</p>
</body>
</html>
EOF_HTML;
Many thanks for the script, ìt looks good and I look forward to trying it tomorrow.
This morning I had another attempt and made a much cleaner version which I uploaded and the modifications can be seen in the latest version.
@davidtsadler
John_Betong:
Many thanks for the script, ìt looks good and I look forward to trying it tomorrow.
This morning I had another attempt and made a much cleaner version which I uploaded and the modifications can be seen in the latest version.
Edit:
I have tried to understand your function but it seems far too complicated for my liking
function highlight(
string $text,
array $words,
array $colors,
bool $ignoreCase = false,
string $format = '<b style="color:%s">%s</b>'
):string
{
$wordToColor = [];
$colorIdx = 0;
$re = '~\\b('.implode('|', $words).')\\b~';
if ($ignoreCase) {
$re .= 'i';
}
return preg_replace_callback
(
$re,
function ($m) use
(
$colors, $format, &$wordToColor, &$colorIdx
):string
{
$word = $m[0];
if ( ! isset($wordToColor[$word]) ) {
$wordToColor[$word] = $colors[$colorIdx];
}
$colorIdx = $colorIdx < count($colors) - 1 ? $colorIdx + 1 : 0;
$color = $wordToColor[$word];
return sprintf($format, $color, $word);
},
$text
);
}
system
Closed
June 9, 2016, 12:26pm
5
This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.