• ベストアンサー

配列の要素を任意の数で割って、割り振る方法

$abc = array("A", "B", "C", "D", "E", "F", "G", "H", "I"); 上記のような配列があったとします。 これを任意の数で割って、割り振っていきたいのですが、例えば7で割ったとしたら、 1. A, B 2. C, D 3. E 4. F 5. G 6. H 7. I という風に、割り振りたいのですが、どのようにすれば、こういったことがPHPのプログラムで実現できるか教えてください。 もしくは、 1. A, H 2. B, I 3. C 4. D 5. E 6. F 7. G という割り振り方でも大丈夫です。

  • h_mp
  • お礼率97% (67/69)
  • PHP
  • 回答数4
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
noname#244856
noname#244856
回答No.3

【foreach ($abc as $i => $v) $new[$i % $max][] = $v;】 $i % $max は剰余を計算するので、$maxが7であるとすると、以下のような順序でループします。 0 % 7 → 0 1 % 7 → 1 2 % 7 → 2 3 % 7 → 3 4 % 7 → 4 5 % 7 → 5 6 % 7 → 6 0 % 7 → 0 1 % 7 → 1 2 % 7 → 2 ... 「もしくは、...という割り振り方でも大丈夫です」ということでしたので、実装しやすいこちらを選びました。 -------------------------------------------- 【$new = array_map(function ($vl) { return implode(', ', $vl); }, $new);】 こちらは2次元配列の中に作成された1次元配列を、「, 」で結合しているだけです。 array(  array('A', 'H'),  array('B', 'I'),  array('C'),  array('D'),  array('E'),  array('F'),  array('G'), ) これが array(  'A, H',  'B, I',  'C',  'D',  'E',  'F',  'G', ) こうなります。 function ($vl) { return implode(', ', $vl); } という無名関数を内側の各配列に対して適用し、returnされてきた文字列を新しい配列にセットしていく感じです。キーはそのまま使用されます。まあ分かりにくかったら [A] $new = array(); $max = count($abc); foreach ($abc as $i => $v) $new[$i % $max][] = $v; foreach ($new as &$v) $v = implode(', ', $v); unset($v); もしくは [B] $new = array(); $max = count($abc); foreach ($abc as $i => $v) $new[$i % $max][] = $v; foreach ($new as $i => $v) $new[$i] = implode(', ', $v); と書くのもナシでは無いです。ただ [A]…「外側でunsetしないと次に$vという変数に代入したときに$newが破壊される」 [B]…「PHPのforeachの実装を理解していないと、現在回している配列自体を書き換えたときの挙動が理解しにくい」 という欠点があります。 -------------------------------------------- 【その他】 まずはマニュアルで気になった関数の使い方を読んでみてください。 [配列関数] http://php.net/manual/ja/ref.array.php メリットがよく分からなければ、以下の記事を読んでみるといいと思います。 [PHPでできる関数型プログラミング] http://my-rest.icca.jp/blog/2011/01/477/ http://my-rest.icca.jp/blog/2011/01/506/ http://my-rest.icca.jp/blog/2011/02/524/ PHPは関数型言語寄りの記述があまり得意ではないので、狂ったみたいにこの書き方に拘る必要はもちろん無いと思います。あくまで「ここは関数型っぽく書いた方がきれいに書ける!」と感じたら採用すればいい程度です。 以下はカレンダーの2次元配列を作成する例ですが、圧倒的に関数型の方がきれいに書ける一例です。 [最もシンプルなカレンダー生成ロジック] http://qiita.com/mpyw/items/0a475bc4891a3a2940e8 ちなみに今回の問題をRubyで解決するならば以下のように書けますね。Rubyはあんまり詳しくないのでもっといい書き方とかあるかもしれませんが、これだけでも十分綺麗に書けてるとは思います。 abc = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'] new = abc  .each_with_index  .group_by{|v, k| k % 7}  .values  .map{|v| v.map(&:first)}

h_mp
質問者

お礼

任意の数字で割るには、$maxの数値を書き換えればいいわけですね。 余りが0から増えていったり、一度2次元配列にして、,でつないで1次元の配列に戻すみたいなやり方は全く発想になかったので、とても勉強になります。 リンクもありがとうございます。 マニュアルや、関数型プログラミングのページ読んでみます。 大変詳しくありがとうございました。

その他の回答 (3)

noname#244856
noname#244856
回答No.4

訂正 0 % 7 → 0 1 % 7 → 1 2 % 7 → 2 3 % 7 → 3 4 % 7 → 4 5 % 7 → 5 6 % 7 → 6 0 % 7 → 0 1 % 7 → 1 2 % 7 → 2 ↓ 0 % 7 → 0 1 % 7 → 1 2 % 7 → 2 3 % 7 → 3 4 % 7 → 4 5 % 7 → 5 6 % 7 → 6 7 % 7 → 0 8 % 7 → 1 9 % 7 → 2

h_mp
質問者

お礼

修正ありがとうございます。

noname#244856
noname#244856
回答No.2

$new = array(); $max = count($abc); foreach ($abc as $i => $v) $new[$i % $max][] = $v; $new = array_map(function ($vl) { return implode(', ', $vl); }, $new);

h_mp
質問者

お礼

回答ありがとうございます。 申しわけないのですが、それぞれどういう意図なのか説明していただけると幸いです。

noname#246457
noname#246457
回答No.1

参考までに テスト(自分のサーバー):http://pro.mnas.0am.jp/TMP/q8833138.php <?php $cnt =7;//任意の数 $abc = array("A", "B", "C", "D", "E", "F", "G", "H", "I"); for($i = 0,$i2 = 0,$i3 = 0 ;$i3 < count($abc);$i ++ , $i3 ++ ){ //配列の場合0からです。 if( $cnt == $i ){ $i = 0; $i2 ++; } $kekka[$i][$i2] = $abc[$i3]; } //結果表示 for($i=0,$i1=0;$i1<count($kekka);$i1++){ echo "".$i1."."; for($i = 0 ; $i < count($kekka[$i1]) ; $i++){ echo $kekka[$i1][$i]; echo ","; } echo "<br />"; } //二個目がないのにかかわらず「,」がつくのは手抜きです。$flagなんて追記したらすぐ修正できます。 exit(); ?>

参考URL:
http://pro.mnas.0am.jp/TMP/q8833138.php
h_mp
質問者

お礼

サーバーにまで上げていただいて、ありがとうございます。 とてもわかりやすいロジックだと思いました。 ありがとうございました。

関連するQ&A

  • 配列から別の配列の要素を削除する方法

    ある配列array_aに、100件の文字列要素が格納されています。 別の配列array_bには、80件の文字列要素が格納されています。 array_aの要素、array_bの要素共に重複するものはありません。 array_b中に存在する要素はすべてarray_a中にも存在します。 array_aにあり、array_bにはない要素で構成されたarray_cの作り方を教えてください。 例えば $array_a=array("a","b","c","d","e","f","g"); $array_b=array("e","b","d"); なら、 $array_c=array("a","c","f","g") になります。 配列array_aとarray_bは、 $array_b=array("b","b","d"); であったり、 $array_a=array("a","a","b","c","d","e","f","g"); といった「重複する要素を含むパターン」はありません。要素はすべてユニークです。 よろしくお願いいたします。

    • ベストアンサー
    • 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
  • mysql_fetch_array結果の配列化

    【ご質問】 あるselect文を実行し、mysql_fetch_arrayで取得した結果を配列したいのですが、どのようにしたら実現できるでしょうか? 【例】 select文の結果で3レコードヒットした場合、 カラム1 カラム2 カラム3 a b c d e f g h i a⇒カラム1[1]、b⇒カラム2[1]、c⇒カラム3[1] d⇒カラム1[2]、e⇒カラム2[2]、f⇒カラム3[2] g⇒カラム1[3]、h⇒カラム2[3]、i⇒カラム3[3]      と配列化したいのです。 ご教授宜しくお願いいたします。

  • JavaScriptの配列について

    var old_array = Array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '<', '#', '/', '>', '%', '.', '*', '0', '!', '?', ':', '=', '|'); var new_array = Array('b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '<', '#', '/', '>', '%', '.', '*', '0', '!', '?', ':', '=', '|'); のような配列があり、 abcと入力するとbcd DEFと入力するとEFG 012と入力すると!23 というようなものを作りたいのですがどうすればいいでしょうか。

  • 関数から呼び出される別の関数でも同じ配列を使うには

    配列をグローバル変数化して、使おうとしています。 <?php $strMoji=array("a","b","c","d","e","f","g","h","i"); $result=fun_disp(2); function fun_disp($i){ global $strMoji; echo $strMoji[$i]; return true; } ?> とすれば、$strMoji[$i];には、c が入っていると表示されました。 ところが、 <?php $result=fun_example(8); function fun_example($j){ echo $j; $strMoji=array("a","b","c","d","e","f","g","h","i"); $result=fun_disp(2); } function fun_disp($i){ global $strMoji; echo $strMoji[$i]; return true; } ?> とすると、$strMoji[$i]; が表示されなくなりました。 やりたいことは、「ある関数内で使っている配列を、その中から呼び出される 別の関数でも使いたい」ということです。 しかし、方法が分からないでいます。どのように書けばいいのでしょうか? ※関数に、2を投げたり8を投げたりしていますが、この値は適当です。

    • ベストアンサー
    • PHP
  • C言語の配列の使い方について質問です。

    以下のプログラムを配列を使って見やすくしたいのですが、どのように作ったら良いでしょうか? 宜しくお願いします。 #include<stdio.h> int main(void) { int a, b, c, d, e, f, g, h, i, j, k, l, m ,n, o; /*5段目の処理*/ for(a = 1; a <= 15; a++) { for(b = 1; b <= 15; b++) { if(a == b) continue; for(c = 1; c <= 15; c++) { if(a == c || b == c) continue; for(d = 1; d <= 15; d++) { if(a == d || b == d || c == d) continue; for(e = 1; e <= 15; e++) { if(a == e || b == e || c == e || d == e) continue; // printf("%d %d %d %d %d\n", a, b, c, d, e); ////4段目//// if(a>b){ f=a-b; } else if(a<b){ f=b-a; } if(b>c){ g=b-c; } else if(b<c){ g=c-b; } if(c>d){ h=c-d; } else if(c<d){ h=d-c; } if(d>e){ i=d-e; } else if(e<d){ i=e-d; } // printf(" %d %d %d %d \n", f, g, h, i); /////3段目//// if(f>g){ j=f-g; } else if(f<g){ j=g-f; } if(g>h){ k=g-h; } else if(g<h){ k=h-g; } if(h>i){ l=h-i; } else if(h<i){ l=i-h; } // printf(" %d %d %d \n", j, k, l); /////2段目//// if(j>k){ m=j-k; } else if(j<k){ m=k-j; } if(k>l){ n=k-l; } else if(k<l){ n=l-k; } // printf(" %d %d \n", m, n); /////三段目///// if(m>n){ o=m-n; } else if(m<n){ o=n-m; } // printf(" %d \n", o); if(a != b != c != d != e != f != g != h != i != j != k != l != m != n != o){ printf("%d %d %d %d %d\n", a, b, c, d, e); printf(" %d %d %d %d \n", f, g, h, i); printf(" %d %d %d \n", j, k, l); printf(" %d %d \n", m, n); printf(" %d \n", o); } } } } } } }

  • ActionScript 配列に関して

    myAry=new Array("a","b","c","d","e","f","g"); というように「myAry」配列の中にa~gまでの7個の要素があるとして、 例えば、myAry[2]; とすると "c"の要素(値)が取り出せますが、 逆に"c"の要素が「myAry」配列の何番目にいるかを調べるにはどうすれば良いのでしょうか? ASのバージョンは1.0もしくは2.0です。

  • ハッシュの中に格納された配列の要素数を得る方法

    予想配列のあるキーを配列とします。 %hash; @hash{'a'}=['aa','ab','ac']; 一方で普通の配列をスカラ変数として扱うと配列数を表します。 @array=(a,b,c,d,e); $num=@array; # $numは5になる。 それでは $num=@hash{'a}; あるいは  $num=@{hash{'a'}}; としたらどうなるのって ARRAY(0x2438c4) みたいになって、$numに@hash{'a'}の要素数は入りません。 予想配列の中に格納された配列の要素数を取り出す簡便な方法はないものでしょうか。 お手数をお掛けします。

    • ベストアンサー
    • Perl
  • 配列の座標指定について。

    たとえば、下のような10行10列の配列でdの3を指定したいときにどういう手段で行えばいいのでしょうか? 入力についてですがdと3の間にはスペースは空けません。 困っています。お願いいたします。 行がそろっていません。みにくいですがお許しください。 \\\a b c d e f g h i j  \\\\\\\\\\\\\\\\\\\\\\\\\\\ 0 \ 0 0 0 0 0 0 0 0 0 0 1 \ 0 0 0 0 0 0 0 0 0 0 2 \ 0 0 0 0 0 0 0 0 0 0 3 \ 0 0 0 0 0 0 0 0 0 0 4 \ 0 0 0 0 0 0 0 0 0 0 5 \ 0 0 0 0 0 0 0 0 0 0 6 \ 0 0 0 0 0 0 0 0 0 0 7 \ 0 0 0 0 0 0 0 0 0 0 8 \ 0 0 0 0 0 0 0 0 0 0 9 \ 0 0 0 0 0 0 0 0 0 0

  • 多次元配列の初期化

    多次元配列の初期化を行いたいのですが、 下記の方法では、配列の値が多くなったときに大変 なので他に良い方法はありませんでしょうか? char lesson[7][6] = { {'A', 'B', 'C', 'D', 'E', 'F'}, {'G', 'H', 'I', 'J', 'K', 'L'}, {'M', 'N', 'O', 'P', 'Q', 'R'}, {'S', 'T', 'U', 'V', 'W', 'X'}, {'Y', 'Z', 'a', 'b', 'c', 'd'}, {'e', 'f', 'g', 'h', 'i', 'j'}, {'k', 'l', 'm', 'n', 'o', 'p'}, };

専門家に質問してみよう