• 締切済み

配列の次元を超えてランダムに選択したい

PHP5.2.4を使用しています。 例えば、次のような2次元以上の配列があったときに $arr[0][0] = array('a' => 1, 'b' => 11); $arr[0][1] = array('a' => 2, 'b' => 5); $arr[0][2] = array('a' => 3, 'b' => 20); $arr[1][0] = array('a' => 4, 'b' => 3); $arr[1][1] = array('a' => 5, 'b' => 30); この5つから、'b'の値が10以上の候補だけのインデックス($arr【[1][1]】←この部分)を ランダムに1つ選ぶ方法はどのようになるのでしょうか? 自分が考えたのは for ($i = 0; $i < count($arr); $i++) {  for ($j = 0; $j < count($arr[$i]); $j++)  {   if ($arr[$i][$j]['b'] < 10)    continue;   $new_arr[] = array('index2' => $i, 'index1' => $j);  } } $key = array_rand($new_arr, 1); print_r($new_arr[$key]); //Array ( [index2] => 0 [index1] => 0 ) //Array ( [index2] => 0 [index1] => 2 ) //Array ( [index2] => 1 [index1] => 1 ) //いずれかが選択される なんですが、これだとあまり良いやり方だと思わなくて なにか別のやり方はあるのでしょうか?

  • PHP
  • 回答数1
  • ありがとう数1

みんなの回答

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

結局もとのデータの持たせ方がわるのでこのようなやり方にならざるをえない ですね・・・。 インデックスを拾う必要があるなら、最初からindexへのデータアクセシビリティを 高めた配列にしておくべきです。 たんにbが10以上の最後の配列にアクセスするだけなら2段階でシャッフルして、 $arr[0][0]にアクセスし、だめなら捨てて次のデータを探すだけで簡単 なんですけどね・・・ <? $arr[0][0] = array('a' => 1, 'b' => 11); $arr[0][1] = array('a' => 2, 'b' => 5); $arr[0][2] = array('a' => 3, 'b' => 20); $arr[1][0] = array('a' => 4, 'b' => 3); $arr[1][1] = array('a' => 5, 'b' => 30); shuffle($arr); shuffle($arr[0]); while(count($arr)>0 and $arr[0][0]['b']<10){ array_shift($arr[0]); if(count($arr[0])==0) array_shift($arr); } print_r($arr[0][0]); ?> やはり構造を一度かえるため、質問者さんのやるようなやりかたに近い こんなふうになるのでしょうか 処理方法としてはシャッフルして合致までするデータを捨てていき、 最初のデータにアクセスするという上記のやり方を踏襲しています <? $arr[0][0] = array('a' => 1, 'b' => 11); $arr[0][1] = array('a' => 2, 'b' => 5); $arr[0][2] = array('a' => 3, 'b' => 20); $arr[1][0] = array('a' => 4, 'b' => 3); $arr[1][1] = array('a' => 5, 'b' => 30); foreach($arr as $index1=>$arr_1){ foreach($arr_1 as $index2=>$arr_2){ $newArr[]=Array('index1'=>$index1,'index2'=>$index2,'array'=>$arr_2); } } shuffle($newArr); while(count($newArr)>0 and $newArr[0]['array']['b']<10){ array_shift($newArr); } print_r($newArr[0]); ?>

takagoo100
質問者

お礼

ご返答ありがとうございます。 ちょっと考えていたのですが、 元のデータの持たせ方が良くないと仰っていますが、 例えば具体的に次のケースではどのような構造にすれば良いのでしょうか? 2つのチーム(チーム0、チーム1)があって、 それぞれのチームにはメンバーがいて、そのメンバーにはそれぞれ共通のパラメータがあります。 チーム0 ・・・ メンバー0_1(パラメータa、パラメータb)、メンバー0_2(パラメータa、パラメータb)、メンバー0_3(パラメータa、パラメータb) チーム1 ・・・ メンバー1_1(パラメータa、パラメータb)、メンバー1_2(パラメータa、パラメータb)、メンバー1_3(パラメータa、パラメータb) これを1つの配列にまとめて扱いたいと考えていて、 そして次のような配列の構造になりました。 $arr[0][0] = array('a' => 1, 'b' => 11); $arr[0][1] = array('a' => 2, 'b' => 5); $arr[0][2] = array('a' => 3, 'b' => 20); $arr[1][0] = array('a' => 4, 'b' => 3); $arr[1][1] = array('a' => 5, 'b' => 30); $arr[1][2] = array('a' => 5, 'b' => 31);//←揃えるため、一つ増やしました このような構造にしたときに、どちらか片方のチームからランダムに選ぶやり方なら uasort関数などを使えば良いとは思いますが、2次元以上(この構造なら2つのチーム) から選ぶとなると厄介だと思い、質問しました。

関連するQ&A

  • 二次元配列に数字をランダムに入れる

    --------------------------- | 2 | 3 | 7 | 4 | 1 || 17 |<横合計> --------------------------- | 6 | 1 | 2 | 3 | / || // | --------------------------- | 1 | / | / | / | / || // | --------------------------- | 2 | / | / | / | / || // | --------------------------- | 3 | / | / | / | / || // | --------------------------- --------------------------- | 14 | / | / | / | / || // |<全合計> --------------------------- <縦合計> このように表示される。 …という処理がしたいのですがどういう処理を書けば良いのかわかりません。 理解した(1)と(2)の乱数発生の文を書いておきます。 *二次元配列を作成* a = new Array(5) for (i = 0; i <= a.length-1; i++){ //1次元 a[i] = new Array(5) for (j = 0; j <= a[i].length-1; j++){ //2次元 a[i][j] = "["+ i +","+ j +"]" var g = ""; document.write(a[i][j]); } } *乱数を100回発生* var z = ""; for(k = 1; k <= 100; k++){ z = Math.round(Math.random()); //発生した乱数をzに代入 } 以上、 よろしくお願いいたします。

  • 割り切れなくなるまで分割して配列に入れたい

    <?php make(7); function make($n) { $arr = array($n); $arr_new = division_arr($arr); print_r($arr_new); } function division_arr($arr) { for ($i = 0; $i < count($arr); $i++) { $arr_new[$i] = division($arr[$i]); if ($arr_new[$i][0] > 0) { return division_arr($arr_new[$i]); } else { } } return $arr_new; } function division($n) { $a = $b = floor($n / 2); if ($n % 2 != 0) { $b+=1; } return array($a, $b); } /* array( [3,4], [[1,2],[2,2]], [[0,1],[1,1],[1,1],[1,1]] ); 再帰的に配列を分割していき、最終的にこのような出力にしたいです。 */ ?> 教えて下さい。よろしくお願いいたします。m(_ _)m

    • ベストアンサー
    • PHP
  • 多次元配列を、1次元の配列にする関数を書いてください。

    以下のように、多次元配列の配列をペチャンコにする関数(array_flatten)ってどうかきますか? <?php $arr[0] = 'a'; $arr[1][0] = 'b'; $arr[1][1][0] = 'c'; $arr[1][1][1][0] = 'd'; $arr[1][1][1][1][0] = 'e'; $arr[1][1][1][2] = 'f'; $arr[1][1][2] = 'g'; $arr[1][2] = 'h'; $arr[2] = 'i'; function array_flatten($arg){   処理; } $new_arr = array_flatten($arr); print_r($new_arr); ?> ↓ Array (   [0] => a   [1] => b   [2] => c   [3] => d   [4] => e   [5] => f   [6] => g   [7] => h   [8] => i ) ※関数のなかで、ペチャンコの配列を格納するための新しい配列を宣言すると、 同関数を再帰的に呼び出したら、その配列が初期化されますよね?

    • ベストアンサー
    • PHP
  • 多次元配列のソートがうまくいかない

    多次元配列のソートがうまくいかない 質問失礼します. 以下のような,String型,int型,double型の混在した多次元配列([3][3]の配列)をソートするプログラムを作成しました. このプログラムでは3番目の項目でソートを行っています. 問題点なのですが, 3番目の項目がdouble型の一桁(例えばarray[1][2]が2.0)ならばうまくソートできるのですが, 一つを2桁(例えばarray[1][2]を10.0)にすると何故か先頭の数(10.0の場合1)を基準にソートされてしまっているようです・・・ 配列へのデータの入れ方が間違っているのでしょうか? 原因がはっきりわからず困っているのですが, わかる方いましたらよろしくお願いします. public class Sort_test { /** * @param args */ public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ String[][] array = new String[3][3]; array[ 0 ][ 0 ] = "A"; array[ 0 ][ 1 ] = 2001+""; array[ 0 ][ 2 ] = 9.0+""; array[ 1 ][ 0 ] = "B"; array[ 1 ][ 1 ] = 1001+""; array[ 1 ][ 2 ] = 2.0+""; array[ 2 ][ 0 ] = "C"; array[ 2 ][ 1 ] = 3001+""; array[ 2 ][ 2 ] = 6.0+""; TheComparator comparator = new TheComparator(); // 3番目の項目でソートするように設定 comparator.setIndex( 2 ); // ソート実施 Arrays.sort( array, comparator ); dump(array); } public static void dump( String[][] array ) { for ( int i = 0;i < array.length;i++ ) { for ( int j = 0; j < array[ i ].length;j++ ) { System.out.print( "\t" + array[ i ][ j ] ); } System.out.println(); } } } //多次元配列ソート用クラス class TheComparator implements Comparator { /** ソート対象のカラムの位置 */ private int index = 0; /** ソートするためのカラム位置をセット */ public void setIndex( int index ) { this.index = index; } public int compare( Object a, Object b ) { String[] strA = ( String[] ) a; String[] strB = ( String[] ) b; return ( strA[ index ].compareTo( strB[ index ] ) ); } }

    • ベストアンサー
    • Java
  • 2件一組の文章をランダムに表示する。

    お世話になっております。 早速ですが、A~Dの文章を2件ランダムに表示させたいです。 更新の度に表示される文章を変えたいのです。 ランダムに文字を並べ替えるコトは出来たのですが、 ソコから2件だけ抜き出すのができません。 <script language="javascript"> arr = ["ほげほげA","ほげほげB","ほげほげC","ほげほげD"]; function a(){ for(i=0; i<arr.length; i++){ k = i; k = Math.floor(Math.random()*arr.length); tmp = arr[i]; arr[i] = arr[k]; arr[k] = tmp; } } function b(){ a(); for(j=0; j<arr.length; j++){ document.write(arr[j]); } } b(); </script> ■1回目 ほげほげC ほげほげA ■2回目 ほげほげA ほげほげD のような感じです。 ご助力お願いいたします!

  • PHPの配列の出力について

    $loop = 5; $count = 0; while($count < $loop){ mt_srand(microtime() * 100000); $rand_key = rand(0,9); if (in_array($rand_key, $yomi)){ $count--; continue; } echo $yomi[$rand_key]\n; } 配列($yomi)に格納されたひらがなから5つ重複させずに選び出したいのですが、 randで選出された「りんご」が2度選び出された場合、これでやり直しされますか? 現在出力出来る環境がありません… 初心者ですので指摘やアドバイス等いただけると嬉しいです。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • しりとり 無限ループ?

    【予約語から最長のしりとりを作ろう!】 https://codeiq.jp/ace/stakemura/q408 この問題やってるんですが 処理がtimeoutしちゃいます 最長の結果が10個程度の時は期待通りに動作します 期待される結果が20程度になると(?)timeoutします 単にウチのマシンじゃムリなのか、工夫が足りないのか 無限ループを起こしてるのか、重いだけなのか判断つきません よろしくお願いします (cpp11_keywords.csvはC++の予約語84個のcsvです) <?php $data=explode(chr(10),file_get_contents('cpp11_keywords.csv')); foreach($data as $i=>$cpp){$data[$i]=trim($data[$i]);} echo(implode('<br/>',createSiritori($data))); function createSiritori($words){ $rtn=array(); $data=array(); for($i=0,$len=count($words);$i<$len;$i++){ $data[$i]=array(); for($j=0;$j<$len;$j++){ if($i==$j)continue; if(is_connectable($words[$i],$words[$j]))$data[$i][]=$j; } } $rcd=0; for($i=0;$i<$len;$i++){ $crr=array($i); for($j_arr=array(0),$j_ind=0,$len_arr=array(count($data[$i]));$j_arr[0]<$len_arr[0];$j_arr[$j_ind]++){ if($j_arr[$j_ind]>=$len_arr[$j_ind]){ array_pop($crr); array_pop($j_arr); array_pop($len_arr); $j_ind--; }else if(!in_array($data[end($crr)][$j_arr[$j_ind]],$crr)){ $crr[]=$data[end($crr)][$j_arr[$j_ind]]; $j_ind++; $j_arr[$j_ind]=0; $len_arr[$j_ind]=count($data[end($crr)]); if($j_ind>$rcd){$rcd=$j_ind;$rtn=$crr;} } } } for($i=0,$len=count($rtn);$i<$len;$i++){ $rtn[$i]=$words[$rtn[$i]]; } return $rtn; } function is_connectable($a,$b){ return (substr($a,-1)==substr($b,0,1)); }

    • ベストアンサー
    • PHP
  • javascriptの2次元配列をソートの仕方

    function word_grouping(data) { var code = data; //先頭についている”code="を除去 code = code.replace("code=",""); var = code.split(","); var alpha =new Array(); alpha = ['A','B','C','D','E','F','G','H','I','J','K','L','M']; //2次元配列作成 var array = new Array(); for (i =0; i < alpha.length; i++) { array[i] = [' ','0']: } //グループ名を格納 for( i = 0; i <alpha.length; i++){ array[i][0] = alpha[i] //0番目の項目から順番にグループごとに分ける for( i = 0; i < sp.length; i++){ group = sp[i].substring(0.1); //どのグループに所属しているか調べる for( j = 0; j < alpha.length; j++){ //一致したグループの配列にカウント+1していく if(group == array[j][0]{ array[j][1]++; } } } メモ ・spにはグループのどこかに所属する20個のキーワードが入っていてそれをグループに振り分けている ・グループ分けには”A001”のAだけみて振り分けています したいこと ・arrayに入ったキーワードの数を降順で並び替えたい 分からない所 ・2次元配列をsortする仕方 こんな感じなんです わかる方回答お願いします。

  • 配列をソートしたいです

    配列をソートしたいです ArrayクラスのsortOn()を使って、 「x座標の大きい順」に順番をならべ変えたいのですが 上手く行きません。。 現在、配列を使い 3つの矩形のSpriteを配置しています。 ↓現在のコード ===================================== var arr:Array = new Array(); for(var i:int=0; i<3; i++){  arr[i] = new Sprite();  with(arr[i].graphics){   beginFill(0x666666);   drawRect(0,0,8,8);   endFill();  }  arr[i].x = i*10;  addChild(arr[i]); } ===================================== 今、各Spriteのxプロパティは  arr[0].x = 0;  arr[1].x = 10;  arr[2].x = 20; になっているのですが、 これをソートして  arr[0].x = 20;  arr[1].x = 10;  arr[2].x = 0; にならべ変えたいのですが、 どのように書けばいいのかがわかりません。。 今、このように書いてるのですが arr.sortOn(arr.x, Array.NUMERIC); 並べ替えができません、 (おそらく arr.x が駄目なのだと思うのですが。。) どなたかご存知の方いらっしゃいましたら どうかよろしくお願いいたします。

    • ベストアンサー
    • Flash
  • 関数内での繰り返し処理の結果を配列で受け取りたい

    関数内でfor文で繰り返し処理を行い、 結果を配列として返すような関数を書きたいと思っています。 function hoge(){ var a = [1,2,3,4]; for (var i=0; i < a.length; i++){ a1 = "a" + i; var arr = new Array(); arr.push(a1); } return arr; } しかし、以下のように 関数hogeの結果を変数bで受け取ってみると、 配列の最後のデータしか表示されません。 var b = hoge(); alert(b); //a3のみが表示される a0, a1, a2, a3と表示されるようにするには、 どうしたらよいでしょうか。

専門家に質問してみよう