试图计算变量内部的数字

时间:2013-12-31 10:35:57

标签: php regex

我正在计算一个变量中有多少个数字。这是我使用的正则表达式..

preg_match('/[^0-9]/', $password, $numbers, PREG_OFFSET_CAPTURE);

当我尝试逐个获取所有数字时,我使用:

print_r($this->filter->password_filter($data["user_password"]));

user_password是123d4sd6789。结果是一个空数组。

Array ( )

3 个答案:

答案 0 :(得分:2)

嗯,您可以使用preg_split轻松完成:

$temp = preg_split('/\d/', $password);
$numCount = count($temp) - 1;

您的正则表达式存在缺陷,因为您尝试使用以下方法计算密码中的位数:

/[^0-9]/

不会削减它,你想要写下来:

/[0-9]/

因为您现在所拥有的内容所有内容除了一个数字。

有很多方法可以做你想要做的事情,我已经对4种不同的方法进行了基准测试,发现使用正则表达式是最快的方法。使用PHP附带的捆绑pcre扩展,preg_split优于所有其他方法~70%的时间,20%的时间,循环更快,而且~10%preg_match_all最快。
在键盘上,由于某种原因,谁不使用标准PCRE,preg_match_all不起作用,shuffle也不可靠,所以我添加了knuth方法,我决定将/\d//[0-9]/之间的差异与preg_split结合使用。在键盘上,正则表达式的结果更快> 95% 简而言之:使用preg_split +正则表达式获得最佳效果。

无论如何,这是基准代码。将它全部放入课堂似乎很愚蠢,但实际上,这是公平的基准测试方式。处理的字符串保存在内存中,用于计时功能的所有数组也都保存在内存中,并比较速度 我也没有直接调用测试方法,而是使用timeCall方法,因为我希望垃圾收集器能够在每次调用后将GC需要GC。无论如何,要想出这个代码并不太难,而且重要的是结果

class Bench
{
    /**
     * @var string
     */
    private $str = '123d4sd6789';

    private $functions = array(
        'regex' => null,
        'regex2' => null,
        'loop' => null,
        'loop2' => null
    );

    private $random = null;

    public function __construct()
    {
        $this->random = array_keys($this->functions);
        if (!shuffle($this->random)) $this->knuth();
    }

    /**
     * Knuth shuffle
     */
    private function knuth()
    {
        for ($i=count($this->random)-1,$j=mt_rand(0,$i);$i>0;$j=mt_rand(0,--$i))
        {
            $temp = $this->random[$j];
            $this->random[$j] = $this->random[$i];
            $this->random[$i] = $temp;
        }
    }

    /**
     * Call all functions in random order, timing each function
     * determine fastest approach, and echo results
     * @param $randomize
     * @return string
     */
    public function test($randomize)
    {
        if ($randomize) if (!shuffle($this->random)) $this->knuth();
        foreach($this->random as $func) $this->functions[$func] = $this->timeCall($func);
        $fastest = array('f', 100000);
        foreach($this->functions as $func => $time)
        {
            $fastest = $fastest[1] > $time ? array($func, $time) : $fastest;
            echo 'Function ', $func, ' took ', $time, 'ms', PHP_EOL;
        }
        echo 'Fastest approach: ', $fastest[0], ' (', $fastest[1], 'ms)', PHP_EOL;
        return $fastest[0];
    }

    /**
     * Time function call
     * @param string $func
     * @return float mixed
     */
    private function timeCall($func)
    {
        echo $func, PHP_EOL;
        $start = microtime(true);
        $this->{$func}();
        return (microtime(true) - $start);
    }

    /**
     * Count digits in string using preg_split
     * @return int
     */
    private function regex()
    {
        return count(preg_split('/\d/', $this->str)) - 1;
    }

    /**
     * count digits in string using str_split + is_numeric + loop
     * @return int
     */
    private function loop()
    {
        $chars = str_split($this->str);
        $counter = 0;
        foreach($chars as $char) if (is_numeric($char)) ++$counter;
        return $counter;
    }

    /**
     * count digits by iterating over string, using is_numeric
     * @return int
     */
    private function loop2()
    {
        for($i=0,$j=strlen($this->str),$counter=0;$i<$j;++$i) if (is_numeric($this->str{$i})) ++$counter;
        return $counter;
    }

    /**
     * use preg_split + [0-9] instead of \d
     * @return int
     */
    private function regex2()
    {
        return count(preg_split('/[0-9]/', $this->str)) - 1;
        if (preg_match_all('/[0-9]/',$this->str, $matches)) return count($matches);
        return 0;
    }

}


$benchmark = new Bench();
$totals = array();
for($i=0;$i<10;++$i)
{
    $func = $benchmark->test($i);
    if (!isset($totals[$func])) $totals[$func] = 0;
    ++$totals[$func];
    if ($i < 9) echo PHP_EOL, '---------------------------------------------', PHP_EOL;
}
var_dump($totals);

Here's the codepad I set up

答案 1 :(得分:0)

你真的想要正则表达式吗?

$arr1 = str_split($password);
$counter=0;
foreach($arr1 as $v){
  if(is_numeric($v))$counter++;
}

答案 2 :(得分:0)

使用preg_match_all选择所有数字:

$reg = '/[0-9]/';
$string = '123d4sd6789';

preg_match_all($reg, $string, $out);
echo (count($out[0]));