2

我有两个要比较的数组,我想知道是否有更有效的方法来做到这一点。

第一个数组是用户提交的值,第二个数组是允许的值,其中一些可能包含通配符来代替数字,例如

// user submitted values
$values = array('fruit' => array(
        'apple8756apple333',
        'banana234banana',
        'apple4apple333',
        'kiwi435kiwi'
        ));

//allowed values
$match = array('allowed' => array(
        'apple*apple333',
        'banana234banana',
        'kiwi*kiwi'
        ));

我需要知道第一个数组中的所有值是否与第二个数组中的值匹配。

这就是我正在使用的:

// the number of values to validate
$valueCount = count($values['fruit']);

// the number of allowed to compare against
$matchCount = count($match['allowed']);

// the number of values passed validation
$passed = 0;

// update allowed wildcards to regular expression for preg_match
foreach($match['allowed'] as &$allowed)
{
    $allowed = str_replace(array('*'), array('([0-9]+)'), $allowed);
}

// for each value match against allowed values
foreach($values['fruit'] as $fruit)
{
    $i = 0;
    $status = false;
    while($i < $matchCount && $status == false)
    {
        $result = preg_match('/' . $match['allowed'][$i] . '/', $fruit);
        if ($result)
        {
            $status = true;
            $passed++;
        }
        $i++;
    }
}

// check all passed validation
if($passed === $valueCount)
{
    echo 'hurray!';
}
else
{
    echo 'fail';
}

我觉得我可能会错过一个比 foreach 循环中的 while 循环做得更好的 PHP 函数。还是我错了?

更新:对不起,我忘了提,数字可能出现在值中超过 1 个位置,但只有 1 个通配符。我已经更新了数组来表示这一点。

4

2 回答 2

2

如果您不想在另一个循环中使用循环,那么将您的$match正则表达式分组会更好。

您可以使用更少的代码获得整个功能,这可能比您当前的解决方案更有效:

// user submitted values
$values = array(
          'fruit' => array(
              'apple8756apple',
              'banana234banana',
              'apple4apple',
              'kiwi51kiwi'
            )
          );


$match = array(
           'allowed' => array(
              'apple*apple',
              'banana234banana',
              'kiwi*kiwi'
            )
          );

$allowed = '('.implode(')|(',$match['allowed']).')';
$allowed = str_replace(array('*'), array('[0-9]+'), $allowed);


foreach($values['fruit'] as $fruit){
  if(preg_match('#'.$allowed.'#',$fruit))
    $matched[] = $fruit;
}

print_r($matched);

见这里:http ://codepad.viper-7.com/8fpThQ

于 2012-07-22T21:43:52.330 回答
1

尝试用'*'替换第一个数组中的/\d+/,然后在两个数组之间执行array_diff()

编辑:澄清后,这里有一个更精致的方法:

<?php
    $allowed = str_replace("*", "\d+", $match['allowed']);
    $passed = 0;
    foreach ($values['fruit'] as $fruit) {
        $count = 0;
        preg_replace($allowed, "", $fruit, -1, $count);    //preg_replace accepts an array as 1st argument and stores the replaces done on $count;
        if ($count) $passed++;
    }
    if ($passed == sizeof($values['fruit']) {
        echo 'hurray!';
    } else {
        echo 'fail';
    }
?>

上面的解决方案并没有消除对嵌套循环的需求,但它只是让 PHP 执行内部循环,这可能会更快(您实际上应该对其进行基准测试)

于 2012-07-22T20:59:39.847 回答