【问题标题】:PHP - Check if a string has only words of less than 4 charactersPHP - 检查字符串是否只有少于 4 个字符的单词
【发布时间】:2017-05-06 10:50:37
【问题描述】:

我需要检查一个查询字符串是否仅由少于 4 个字符的单词组成,如果是,则删除所有空格。

类似:this has four character words or higher ... 将返回 FALSE

类似:hd 1 kit ... 将返回 TRUE,因为字符串中的单词不超过 3 个字符。

我会尝试对其进行编码,但对于如何为此类内容编写正则表达式一无所知。

【问题讨论】:

    标签: php regex


    【解决方案1】:

    您可以使用@SahilGulati 建议的正则表达式来执行此操作,但使用explode() 可能更有效:

    $string = "this has four character words or higher";
    $array = explode(" ", $string);
    $success = true;
    foreach ($array as $word) {
        if(strlen($word) < 4) {
            $success = false;
            break;
        }
    }
    if($success) {
        echo "ok";
    } else {
        echo "nok";
    }
    

    这是live example


    here 是使用正则表达式和非正则表达式的实时比较(不使用正则表达式时大约快 35%):

    <?php
    function noRegex() {
        $string = "this has four character words or higher";
        $array = explode(" ", $string);
        $success = true;
        foreach ($array as $word) {
            if(strlen($word) < 4) {
                $success = false;
                break;
            }
        }
        return $success;
    }
    function regex() {
        $string = "this has four character words or higher";
        $success = false;
        if(!preg_match_all("/\b[a-zA-Z0-9]{4}\b/", $string)) {
            $success = true;
        }
        return $success;
    }
    
    $before = microtime(true);
    for($i=0; $i<2000000; $i++) {
        noRegex();
    }
    echo "no regex: ";
    echo $noRegexTime = microtime(true) - $before;
    echo $noRegexTime;
    echo "\n";
    
    $before = microtime(true);
    for($i=0; $i<2000000; $i++) {
        regex();
    }
    echo "regex: ";
    echo $regexTime = microtime(true) - $before;
    echo $regexTime;
    echo "\n";
    
    echo "Not using regex is " . round((($regexTime / $noRegexTime) - 1) * 100, 2) . "% faster than using regex.";
    ?>
    

    【讨论】:

    • 我选择了我选择的答案,因为我处于使用率较低的环境中,查询已经在不到一秒的时间内得到处理。我更喜欢更少的代码。我的最终结果:$query = (!preg_match_all("/\b[a-zA-Z0-9]{4,}\b/", $query) ? str_replace(" ","",$query) : $query );
    • 此解决方案不尊重标点符号。使用正则表达式,您根本不考虑它们,但使用爆炸,您需要修剪它们,我猜。
    • 你为什么要在你的基准测试中使用preg_match_allreturn (bool)!preg_match("/\b[a-zA-Z0-9]{4}/", $string); 它的性能优于 noregex。
    • 我使用了与 SahilGulatis 的答案相同的代码 sn-p。是的,在这个例子中没有考虑标点符号。
    【解决方案2】:

    希望这个简单的解决方案能帮到你。

    正则表达式: /\b[a-zA-Z0-9]{4,}\b/

    1. \b[a-zA-Z0-9]{4,}\b 将匹配四个字符,\b 用于边界条件。

    <?php
    
    $string1="this has four character words or higher";
    $string2="hd 1 kit";
    
    if(!preg_match_all("/\b[a-zA-Z0-9]{4,}\b/", $string1))
    {
        echo "Should be allowed";
    }
    

    【讨论】:

    • 谢谢,工作完美,我应该想到,为什么不尝试搜索至少 4 个字符中的 1 个单词,并从中判断为真/假。非常感谢!
    • 如果你认为你只需要一个至少四个字符的单词,你可以让它更简单。
    • @CasimiretHippolyte 我已经更改了它,因为 SO 上的一个好人给了我这样的字符串 I am Sahil。这没有4 字符的单词,但它应该被禁止..
    • 我在想:if (!preg_match("/\b[a-zA-Z0-9]{4}/", $string1))
    • @CasimiretHippolyte 是的,这也可能是正确的......对的人...... :)
    【解决方案3】:

    如果字符串中没有标点符号,那么最有效的方法是使用strpos

    function checkWordsLenght($string, $limit)
    {
        $offset = 0;
        $string .= ' ';
    
        while(($position = strpos($string, ' ', $offset)) !== false) {
            if (($position - $offset) > $limit) {
                return false;
            }
    
            $offset = $position + 1;
        }
    
        return true;
    }
    

    这里是working demo

    【讨论】:

      【解决方案4】:

      重要的是,在提供基于正则表达式的解决方案时,被视为“最佳”的答案是最精炼的。这意味着提供最准确的结果,当结果准确度并列时,性能应该是下一个标准,其次是模式简洁性。

      出于这个原因,我不得不发布一个优于当前接受的答案的答案。我将使用 V_RocKs 在 ssc-hrep3 的答案下的评论中使用的变量名。

      使用第一个示例字符串的代码:

      $query="this has four character words or higher";
      $query=preg_match("/[^ ]{4,}/",$query)?str_replace(" ","",$query):$query;
      echo "$query";
      

      输出:

      thishasfourcharacterwordsorhigher
      

      使用第二个示例字符串的代码:

      $query="hd 1 kit";
      $query=preg_match("/[^ ]{4,}/",$query)?str_replace(" ","",$query):$query;
      echo "$query";
      

      输出:

      hd 1 kit
      

      我的正则表达式模式不仅同样准确,而且更短、更高效(需要更少的步骤)。对于这个问题,边界字符的使用是不必要的,它会对性能产生近 50% 的负面影响。

      从模式中删除单词边界后,有几种方法可以定位所需的子字符串。以下模式具有完全相同的含义和steps 计数:

      • /[a-zA-Z0-9]{4,}/
      • /[a-z0-9]{4,}/i
      • /[a-z\d]{4,}/i
      • /[^ ]{4,}/

      我的观点是:读者来 SO 并不是为了寻找“嗯,这已经足够好”的答案了,他们来这里是为了从才华横溢、多元化的 SO 社区的庞大知识库中汲取灵感/教育方法。让我们努力在每个答案上实现最佳方法,以便未来的读者可以从我们的见解中学习,并接受所有编码语言所提供的教育。

      当次优模式在 SO 上获得支持/绿色标记时,就错失了正确教育读者完成编码任务的最佳方法的机会。

      【讨论】:

        猜你喜欢
        • 2020-02-19
        • 2011-12-13
        • 1970-01-01
        • 1970-01-01
        • 2020-03-10
        • 2017-02-28
        • 1970-01-01
        • 2020-03-22
        • 1970-01-01
        相关资源
        最近更新 更多