Regexp PHP显示最小的比赛



我正在尝试获得php中的regexp的最小匹配。

例如:如果我有电视和电话单词,并且用户输入为TEL,则我的Regexp应该返回最小的单词,在这种情况下为电话。简而言之,我试图像搜索脚本一样做。但是对于用户输入中缺少的字母,我使用此 t[a-zA-Z0-9]{0,2}l[a-zA-Z0-9]{0,},所以我的最后一个字母表格将以n个字符。

我的问题是:我该如何做我的言论以显示最小的单词。

不幸的是您无法做到。Regex可以匹配您想要的东西,但没有提供任何功能来比较subbatches。您必须匹配整个字符串,并在您的情况下按PHP代码进行比较。

// your array of matched words
$words = array(...);
$foundWordLength = null;
$foundWord = '';
foreach ($words as $word) {
   if (strlen($word) < $foundWordLength || $foundWordLength === null) {
      $wordLength = strlen($word);
      $foundWord = $word;
   }
}
echo $foundWord;

我认为您可以使用正则表达式实现它的唯一方法是首先按照理想的顺序对单词进行排序,从最短到最长的情况下。

那么,如果您的单词相对较少,为了性能,可以同时将单词串联并检查第一个匹配项。可能是因为PHP Regexp实现从左到右执行搜索。请参阅下面的示例中的函数search_short()

无论如何,从最低点开始的循环和检查单词也将起作用。在下面的示例中检查功能search_long()

<?php
$given = [
    'telephone',
    'television',
];
// NB: Do not forget to sanitize user input, i.e. $query
echo (search_short($given, 'tele') ?: 'Nothing found') . PHP_EOL;
echo (search_long($given, 'tele') ?: 'Nothing found') . PHP_EOL;
echo (search_short($given, 't[a-zA-Z0-9]{0,2}l[a-zA-Z0-9]{0,}') ?: 'Nothing found') . PHP_EOL;
echo (search_long($given, 't[a-zA-Z0-9]{0,2}l[a-zA-Z0-9]{0,}') ?: 'Nothing found') . PHP_EOL;
/**
 * @param string[] $given
 * @param string   $query
 *
 * @return null|string
 */
function search_short($given, $query)
{
    // precalculating the length of each word, removing duplicates, sorting
    $given = array_map(function ($word) {
        return mb_strlen($word); // `mb_strlen()` is O(N) function, while `strlen()` is O(1)
    }, array_combine($given, $given));
    asort($given);
    // preparing the index string
    $index = implode(PHP_EOL, array_keys($given));
    // and, finally, searching (the multiline flag is set)
    preg_match(
        sprintf('/^(?<word>%sw*)$/mu', $query), // injecting the query word
        $index,
        $matches
    );
    // the final pattern looks like: "/^(?P<word>telew*)$/mui"
    if (array_key_exists('word', $matches)) {
        return $matches['word'];
    }
    return null;
}
/**
 * @param string[] $given
 * @param string   $query
 *
 * @return null|string
 */
function search_long($given, $query)
{
    $pattern = sprintf('/^(?<word>%sw*)$/u', $query);
    // precalculating the length of each word, removing duplicates, sorting
    $given = array_map(function ($word) {
        return mb_strlen($word);
    }, array_combine($given, $given));
    asort($given);

    foreach ($given as $word => $count) {
        if (preg_match($pattern, $word, $matches)) {
            if (array_key_exists('word', $matches)) {
                return $matches['word'];
            }
        }
    }
    return false;
}

当然,这不是最有效的算法,并且可以通过多种方式得到改进。但是,要完成有关所需范围和用法的更多信息。

正则表达引擎通常没有预定的内存来存储复杂条件,也没有从编程语言功能中受益以提供复杂的比较。

如果没有漫无目的地执行标记的PHP,您可以再做几行完成工作。

$str = 'television and telephone';
preg_match_all('/telw*/', $str, $matches);
usort($matches[0], function($a, $b) {
    return strlen($a) <=> strlen($b);
});
echo $matches[0][0];

最新更新