プロが教えるわが家の防犯対策術!

やりたいことは、

$hoge = array ( 0 => '1', 1 => '2', 2 => '3', 3 => '3', 4 => '3' );

のような配列があったとします。

この配列の値の出現頻度を調べて、

$hoge_syutugen_hindo = array_count_values($hoge);

print_r($hoge_syutugen_hindo);

$hoge_syutugen_hindoの結果
Array ( [1] => 1 [2] => 1 [3] => 3 )

$hoge_syutugen_hindoの結果で[3]の出現頻度が3回以上あったら、

Array ( [1] => 1 [2] => 1 [3] => 3 ) を Array ( [1] => 1 [2] => 1 [4] => 1 ) に変更。

少ない場合は

Array ( [1] => 1 [2] => 1 [3] => 2 ) を Array ( [1] => 1 [2] => 1 [3] => 2 )

そのままの配列を返したいのです。

$hogeの配列の値には必ずしも1や2が含まれるわけではありません。

$hoge = array ( 0 => '3', 1 => '3', 2 => '3' ); や$hoge = array ( 0 => '1', 1 => '3', 2 => '3', 3 => '3' ); のようなパターン等もあります。


わたしなりに下記のようなスクリプトを作成しましたが、

$arr_pattern = '/^(3\s=>\s)[3-99]$|^(3=>)[3-99]$|^(3=>\s)[3-99]$|^(3\s=>)[3-99]$|^(3\s=>\s)\'[3-99]\'$|^(3=>)\'[3-99]\'$|^(3=>\s)\'[3-99]\'$|^(3\s=>)\'[3-99]\'$|^(\[3\]\s=>\s)[3-99]$|^(\[3\]=>)[3-99]$|^(\[3\]=>\s)[3-99]$|^(\[3\]\s=>)[3-99]$|^(\[3\]\s=>\s)\'[3-99]\'$|^(\[3\]=>)\'[3-99]\'$|^(\[3\]=>\s)\'[3-99]\'$|^(\[3\]\s=>)\'[3-99]\'$/';

reset($deliyery_kind_syutu);

while(list($k, $v) = each($deliyery_kind_syutu)) {

$kv = "$k=>$v";

if(preg_match($arr_pattern, $kv)){
$new_hkv = preg_replace($arr_pattern,'4 => 1', $kv);

$n = count($deliyery_kind_syutu);
for($i=0; $i<$n; $i++){
$new_array[] = ($deliyery_kind_syutu[$i]);
}
$new_array[] = $new_hkv;
}
}

array ( 0 => NULL, 1 => 1, 2 => 1, 3 => '4 => 1', )となり、array(1 => 1, 2 => 1, 4 => 1)のような結果になりませんでした。

分かる方が見えましたらご教授ください。

A 回答 (3件)

あ、3回より多いじゃなくて3回以上でよかったんでしたっけ?



if($hoge_syutugen_hindo[3]>3){
のところを
if($hoge_syutugen_hindo[3]>=3){
つまり、「以上」にしてみてください
    • good
    • 0
この回答へのお礼

yambejp様

条件分岐だけのために回答いただきまして、ありがとうございます。
回答いただく前に3回以上で動作させていただきました。

結果は
Array ( [1] => 1 [2] => 1 [4] => 1 )

と思うような処理ができました。
ありがとうございました。

unset()関数が今回のみそでした。
いろいろ、削除する関数を探したのですが、どれも思うような関数にめぐり会えませんでしたが、unset()関数はいいですね。

条件にあった関数をおしえていただきありがとうございました。

お礼日時:2008/12/05 13:52

そうですか・・・、そういう仕様であるなら仕方ないですね。


以下でよいのでは?

$hoge_syutugen_hindo = array_count_values($hoge);
if($hoge_syutugen_hindo[3]>3){
unset($hoge_syutugen_hindo[3]);
$hoge_syutugen_hindo[4]++;
//もしくは$hoge_syutugen_hindo[4]=1;
}

この回答への補足

yambejp様
失礼いたしました。
if文を外すと思うような結果になっていました。
それを確かめず、展開が必要なのではと発言してしまってすいませんでした。

>$hoge = array ( 0 => '1', 1 => '2', 2 => '3', 3 => '3', 4 => '3' );

>$hoge_syutugen_hindo = array_count_values($hoge);

>//if($hoge_syutugen_hindo[3]>3){
>unset($hoge_syutugen_hindo[3]);
>$hoge_syutugen_hindo[4]++;
>//もしくは$hoge_syutugen_hindo[4]=1;
>//}

print_r($hoge_syutugen_hindo);

結果

Array ( [1] => 1 [2] => 1 [4] => 1 )

処理は条件を満たしていました。

条件分岐だけのうまく働きませんでした。

補足日時:2008/12/05 13:00
    • good
    • 0
この回答へのお礼

yambejp様 早速の回答ありがとうございます。

動作させてみたところ

>$hoge = array ( 0 => '1', 1 => '2', 2 => '3', 3 => '3', 4 => '3' );

>$hoge_syutugen_hindo = array_count_values($hoge);

>if($hoge_syutugen_hindo[3]>3){
>unset($hoge_syutugen_hindo[3]);
>$hoge_syutugen_hindo[4]++;
>//もしくは$hoge_syutugen_hindo[4]=1;
>}

print_r($hoge_syutugen_hindo);

結果
Array ( [1] => 1 [2] => 1 [3] => 3 ) ;

以下の結果でした。

どうやら、if文が働かないみたいです。

わたしが思うに展開してキーと値に分けて、処理しないとできないような気がします。

展開せずに処理できる関数があればそれに越したことはありません。

reset($hoge_syutugen_hindo);

while(list($key, $value) = each($hoge_syutugen_hindo)) {

if($key==3 && $value>3){

$key=4;
$value=1;

}else{

$key;
$value;
}


のような展開して新しく配列を作成しなければいけないような----

わたしもこれから先どう配列化すれば良くはわからないのですが----

また、よろしくお願いします。

お礼日時:2008/12/05 12:45

仕様が破たんしていませんか?



>$hoge_syutugen_hindoの結果で[3]の出現頻度が3回以上あったら、

>Array ( [1] => 1 [2] => 1 [3] => 3 ) を
>Array ( [1] => 1 [2] => 1 [4] => 1 ) に変更。

揚足をとるようで申し訳ないですが、仕様確定のため・・・
「[3]の出現頻度が3回以上」となっていますが
「Array ( [1] => 1 [2] => 1 [3] => 3 )」の時点ですでに3回以上ですね?
もし仮にこれが、4回以上だと読み替えたとしても、

Array ( [1] => 1 [2] => 1 [3] => 4(or more) )
ではなく、
Array ( [1] => 1 [2] => 1 [4] => 1 )
となる状況がわかりません
これがまかり通る場合、
Array(1,2,3,3,3,3)もArray(1,2,4)も同じになりますね?
仕様が競合していますがそれでよいのでしょうか?
Array(1,2,3,3,3,3,4)の場合は
Array ( [1] => 1 [2] => 1 [4] => 2 )
なのでしょうか、それとも他の値なのでしょうか?

またArray(1,2,3,3,3,3,3)の場合も
Array ( [1] => 1 [2] => 1 [5] => 1 )ではなくキーは4なのでしょうか?
    • good
    • 0
この回答へのお礼

早速の回答恐れ入ります。

>Array ( [1] => 1 [2] => 1 [4] => 1 )となる状況がわかりません
>これがまかり通る場合、
>Array(1,2,3,3,3,3)もArray(1,2,4)も同じになりますね?
>仕様が競合していますがそれでよいのでしょうか?

確かに仕様が競合していますが、それでいいです。

とにかく、3の動作だけは2回出現したらやめて、それ以降は4の動作にしたいのです。

4の動作は3の動作が3回以上のみ働く特別な動作であり、これ以外の動作はありません。5の動作はありません。

ですから、4の動作になったと分かればそれでいいので、[4] => 1でいいのです。

普通から考えれば、yambejp様のおしゃるとおり、おかしいと思うが当然ですが、今回はこの仕様でいいのです。

よろしくお願いします。

お礼日時:2008/12/05 10:17

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!