PHP pattern Matching from more precise to less in an array

I am trying to create a function in PHP that matches a string, allows you to say “1234567” with the best matching match prefix, although there are a few matches, select the best one.

For example, if we have all of this:

(1, 12, 123, 1234, 456, 56, 7, 3456, 234567)

Input = "1234567"

The output must be = "1234"

Because the prefix that matches the best (despite 1, 12 and 123 matching, is also no better than 1234, and despite the fact that 234567 is the best match in general, it is not a prefix).

I do not know if this function is implemented by default in PHP

+4
source share
4 answers

Detach the prefixes in length from the longest to the shortest. Then return the first match.

function bestMatch($input, $prefixes)
{
    usort($prefixes, function($a, $b) { return strlen($b) - strlen($a); });

    foreach ($prefixes as $prefix) {
        if (strncmp($input, $prefix, strlen($prefix)) === 0) {
            return $prefix;
        }
    }

    return false; // or whatever you want to return for "no match"
}

, foreach, .

+3

PHP , ...

, , , :

function get_best_prefix($input, array $prefixes)
{
        // Walk through all the possible prefixes and eliminate 
        // the non-matching ones by setting them to null
        array_walk(
                $prefixes,
                function(&$value, $key, $input)
                {

                        if (strncmp($input, $value, strlen($value)) !== 0)
                        {
                                $value = null;
                        }
                },
                $input
        );

        // Not really necessary, but let eliminate duplicate elements
        $prefixes = array_unique($prefixes, SORT_STRING);

        // Sort the remaining prefixes (all valid ones at this point)
        // by length, putting the highest-length ones at the top 
        usort(
                $prefixes,
                function($a, $b)
                {
                        return (strlen($a) > strlen($b)) ? -1 : 1;
                }
        );

        // Get the first element of the array, which is now the 
        // longest possible prefix that we have. There the 
        // possibility of the array being empty or containing 
        // only a single null value, but that OK - null would 
        // be returned in both cases.
        return array_shift($prefixes);
}
+2

Iterate over all possible matches and save them in a new array. You can use strposto check if your substring is the prefix of your input. You can order them depending on how long they will be.

$input = '1234567';
$array = ['1', '12', '123', '1234', '456', '56', '7', '3456', '234567'];

$results = [];
foreach ($array as $data) {
    if (strpos($input, $data) === 0) {
        $results[strlen($data)][] = $data;
    }
}

krsort($results);

// best results - you can use foreach to scroll them all
var_dump($results);

// pick the best result
echo current($results)[0]; // 1234

Demo .

+1
source

If you just want the best, and you don’t need to know someone else’s match.

/**
 *
 * @param string $input
 * @param array $array
 * @param int $limit [Optional, limit of iterations before giveup. Default -1 ( no limit ).]
 * @param int $count [Optional, If specified, this variable will be filled with the number of replacements done.] 
 * @return type
 */
function get_best_prefix($input, $array, $limit = -1, &$count = null) {

  $best = '';
  $sizeBest = 0;
  $count = 0;

  foreach ($array as $data) {
    if (strpos($input, $data) === 0) {
      $current = strlen($data);

      if ($sizeBest < $current) {
        $sizeBest = $current;
        $best = $data;
      }

      $count++;
      if ($limit > -1 AND $count >= $limit) {
        break;
      }
    }
  }

  return $best;
}

$input = '1234567';
$array = ['1', '12', '123', '1234', '456', '56', '7', '3456', '234567'];
echo get_best_prefix($input, $array);
+1
source

Source: https://habr.com/ru/post/1612805/


All Articles