• 締切済み

キーが倍数の時の値の存在チェック方法

PHP5.2.4を使用しています。 連想配列のキーが[]で囲まれている時、 その中の数字が倍数としてチェックされるとします。 次の例では、3と4の倍数の時に条件(if (is_int($wk)))に引っかかり キーの値(3の倍数です、など)が表示されます。 ただこのやり方だと、foreachでループさせないと倍数かどうかが分からないので、 もっと効率の良い(isset($arr[$i])で調べられるような)調べ方はできないでしょうか? $arr = array(  '1' => '1です',  '2' => '2です',  '[3]' => '3の倍数です',  '[4]' => '4の倍数です', ); for ($i = 1; $i < 15; $i++) {  if (isset($arr[$i])) //←全てこの(簡単な)条件式で調べられれば良いのですが・・・  {   print "{$arr[$i]}<br>\n";  }  foreach ($arr as $key => $value)//←キーが倍数かはどうしても全てのキーをチェックせざるえない  {   if (preg_match("/\[(\d+)\]/", $key, $match))   {    $wk = $i / $match[1];    if (is_int($wk)) //←除算した結果が整数ならその倍数だと判明    {     print "i={$i} {$arr[$match[0]]}<br>\n";    }   }  } } 1です 2です i=3 3の倍数です i=4 4の倍数です i=6 3の倍数です i=8 4の倍数です i=9 3の倍数です i=12 3の倍数です i=12 4の倍数です i=15 3の倍数です

みんなの回答

  • masa6272
  • ベストアンサー率66% (93/140)
回答No.4

こんなのは、どうでしょう? <?php $arr = array(   '1' => '1です',   '2' => '2です',   '[3]' => '3の倍数です',   '[4]' => '4の倍数です', ); foreach($arr as $k => $v) {   if(preg_match('/\[(\d+)\]/', $k, $m)) {     $arrCheck[$m[1]] = $v;   } else {     $arrNoCheck[$k] = $v;   } } for($i = 1; $i < 15; $i++) {   if(isset($arrNoCheck[$i])) {     echo "{$arr[$i]}<br>\n";   } else {     foreach($arrCheck as $k => $v) {       if($i % $k == 0) {         echo "i={$i} {$arrCheck[$k]}<br>\n";       }     }   } } ?>

takagoo100
質問者

お礼

ご返答ありがとうございます。 いくらかは効率が良くなっていますが、 やっぱり >   foreach($arrCheck as $k => $v) { を使っているということは、 ほとんどの$iに対して調べるということなので このループを使わずにできないものでしょうか?

  • little-m
  • ベストアンサー率44% (45/102)
回答No.3

倍数チェック用の配列 ($arr2) を前もって作成してチェックすれば isset() にてチェック可能なロジックが組めるのではと思います。以下のようなロジックではどうでしょうか? しかしながら、これが全ループで逐次チェックする方法に比べて計算回数が多いか少ないかは当方もわかりません。 (ロジック例) $imax = 100;  // $i の最大値 $arr2 = array(); foreach ($arr as $key => $val) {  if (substr($key, 0, 1) == '[')  {   $num = substr($key, 1, -1);   if ($num <= 0) { print('error'); exit; }   $jmax = (int)($imax / $num);   for ($j = 1; $j <= $jmax; $j ++)   {    $k = $j * $num; // 倍数    if (!isset($arr2[$k])) { $arr2[$k] = array(); }    $arr2[$k][] = $val;   }  } } for ($i = 1; $i <= $imax; $i++) {  if (isset($arr[$i]))  {   print "{$arr[$i]}<br>\n";  }  if (isset($arr2[$i]))  {   print join("<br>\n", $arr2[$i]);  } }

takagoo100
質問者

お礼

ご返答ありがとうございます。 なるほど、こういうやり方もあるわけですね。 確かにキーの数によるとは思いますが、 自分が示した例よりは効率が良いような気がします。

回答No.2

倍数かどうかの判定は余りを求める剰余演算子「%」で結果が0かどうかを調べれば簡単にだせるかとおもいます。 for ($i = 1; $i < 15; $i++)  print "i=" . $i;  if($i % 3 == 0){   print " 3の倍数です";  }  if($i % 4 == 0){   print " 4の倍数です";  }  print "<br>\n"; }

参考URL:
http://jp2.php.net/manual/ja/language.operators.arithmetic.php
takagoo100
質問者

お礼

ご返答ありがとうございます。 確かにそうなんですが、3の倍数か5の倍数か8の倍数か どの倍数がその配列にセットされてるかは分からなくて それを調べるという作業をやりたいのです。 saintandreさんのやり方だと、 3の倍数がキーにセットされてるか調べる時は  if($i % 3 == 0){   print " 3の倍数です";  } 4の倍数がキーにセットされてるか調べる時は  if($i % 4 == 0){   print " 4の倍数です";  } とその都度書き足さないといけなくて、 ではループなら自分が示した例( QNo.4051581のforeach ($arr as $key => $value)//←キーが倍数かはどうしても全てのキーをチェックせざるえない )のように一つにまとめて書くことができるのですが、 それは効率が悪そうなのでやりたくないのです・・・ できれば、1や4など(つまり倍数としてじゃなく)を調べる if (isset($arr[$i])) のようにループを使わずにそのキーがセットされてるか調べたいのですが このようなことは可能なのでしょうか?

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

gmpライブラリでソースを簡略化できるかもしれません http://www.php.net/manual/ja/book.gmp.php ちなみに命題があいまいでよくわからないのですが・・・ これは素数以外のデータをとりたいということでしょうか? そうなると3は素数ですが、3は3の倍数というのが理解できません。 4は2の倍数ですよね?14は2の倍数ですがよろしいのでしょうか?

takagoo100
質問者

お礼

ご返答ありがとうございます。 すいません、 自分も内容の説明もそうですが、どういう題名をつけるべきか迷いました・・・ >http://www.php.net/manual/ja/book.gmp.php 見てみたのですが、この中にはなさそうだと思うのですが、、 何か使えるのはあるのでしょうか? これは素数とかは関係なくて、 $iの値が 3の倍数なら3,6,9,12・・・ 4の倍数なら4,8,12,16・・・ となったときに、そのキーの$arrがセットされてるか値を調べたいのです。 単にキーが1とか3なら if (isset($arr[$i])) で値がセットされてるか調べられますよね。 だけど、5の倍数の時を調べたいとなると、 if (isset($arr[$i])) ↑このやり方だと、$iがループしてきて5の時は調べられますけど 次の10や15のときはこのままの条件式だと無理ですよね? でもだからといってforeachを使ってまた全部のキーを調べるやり方は 効率が悪いのでやりたくないです。

専門家に質問してみよう