skip to Main Content

I want to highlight my search query on a formatted number.

For example:

$search_query = '1234'; // or $search_query = '7800';
$formatted_numeber = '12,345,678.00';

Currently my code is:

preg_replace('/(' . $search_query . ')/i', "<span style='background: yellow'>$1</span>", $formatted_numeber);

But this code fails to highlight search clause like ‘1234’ , ‘7800’ due to presence of commas (,) and decimal (.)

Also i want this to work with the presence of commas and decimals in the search query.

For example:

$search_query = '3,456';
$formatted_numeber = '12,345,678.00';

I want to highlight the part "345,6" on my formatted number.

Or:

$search_query = '7.80';
$formatted_numeber = '12,345,678.00';

I want to highlight the part "78.0" on my formatted number.

2

Answers


  1. Given how long is takes to get an answer, I think we can conclude that this isn’t a trivial problem.

    I assume, although you don’t explicitly say so, that you actually only want to highlight formatted numbers, and that these numbers aren’t embedded in a bigger text. I also assume you only want to highlight one part of the number, not multiple parts. So in 12,341,234.00 only the first 1234 will be highlighted.

    My solution is a real algorithm, and not based on complex build-in functions or regular expressions. That would be possible of course, but I avoided them.

    function highlight(string $search, string $number): string
    {
        $searchBegin = NULL;
        $searchIndex = 0;
        $search      = str_replace([',', '.'], '', $search);
        foreach (str_split($number) as $numberIndex => $character) {
            if ($character == $search[$searchIndex]) {
                if (is_null($searchBegin)) {
                    $searchBegin = $numberIndex;
                }    
                $searchIndex++;
                if ($searchIndex == strlen($search)) {
                   return substr($number, 0, $searchBegin) .
                          '<span style="background: yellow">' .
                          substr($number, $searchBegin, $numberIndex - $searchBegin + 1) .
                          '</span>' .
                          substr($number, $numberIndex + 1);                
                }
            } elseif (!in_array($character, [',', '.']))  {
                $searchBegin = NULL;
                $searchIndex = 0;
            }
        }
        return $number;
    }
    

    Live demo: https://3v4l.org/StFn7

    I think the code is quite self-explanatory. Just follow what it does and you’ll understand it. There’s nothing mysterious about it.

    This code isn’t optimized, and doesn’t check for errors. It is intended as a starting point for further optimization. str_split() is handy, but not very fast, you can easily make this algorithm faster by using a for loop and a string index. Being able to highlight multiple sections would be the first thing I would do. You could do this recursively on the part of the $number after the match. Like so: https://3v4l.org/aRZtN

    This code might be longer than you expect, but that doesn’t make it bad or slow code. Sometimes a good old-fashioned algorithm wins the day.

    Login or Signup to reply.
  2. To use PHP’s preg_replace() to search for a formatted number (which may contain commas and decimal points) and replace it based on a query (while ignoring commas and decimal points), you can first normalize the number by removing commas and decimal points before performing the search. Then, you can format the result as needed after the replacement.

    <?php
    
    function regex(string $search, string $number): string
    {
      
        $search = str_replace([',', '.'], '', $search);
    
        $pattern = '/b' . preg_quote($search, '/') . 'b/';
    
        
        $show = preg_replace_callback($pattern, function ($matches) use ($number) {
            $search = $matches[0];
            $search = str_replace([',', '.'], '', $search); 
            
            return '<span style="background: yellow">' . $search . '</span>';
        }, $number);
    
        return $show;
    }
    
    ?>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search