2

比較している2つのアレイがあり、それを行うためのより効率的な方法があるかどうかを知りたいです。

最初の配列はユーザ​​ーが送信した値であり、2番目の配列には許可された値があり、その一部には数値の代わりにワイルドカードが含まれている場合があります。

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

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

最初の配列のすべての値が2番目の配列の値と一致するかどうかを知る必要があります。

これは私が使用しているものです:

// 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つしかありません。これを表すために配列を更新しました。

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 +/を'*'に置き換えてから、2つの配列間で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 に答える