LoginSignup
0
0

More than 5 years have passed since last update.

phpで[0,...10]までの配列を2個、3個、2個……となるようにarray_chunkしようとしたら大変なことになった

Posted at

たまにこういうことってあると思うんですね。
画面上の列の構成が1行目は2個、2行目は3個……みたいな。
CSSで対応できないこともないんですが、PHP側でそういう対応が必要になってしまった場合に。

2個ずつ、3個ずつ、ということであればarray_chunk一発で簡単だったんですが……

まずはシンプルにッ!

simple_chunk.php
$azunyan = range(0, 10);

$peropero = [];
while (count($azunyan)) {
    $peropero[] = array_splice($azunyan, 0, count($peropero) % 2 ? 3 : 2);
}

// [[0,1], [2,3,4], [5,6], [7,8,9], [10]]
var_dump($peropero);

シンプルに実装してみました。
2個、3個となるように、array_spliceに渡す値を制御しています。
生のPHPでやるのであれば、これが普通だと思います。

:fire::fire:燃え上がる反骨心:fire::fire:

:fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire:
何をトチ狂ったのか、\$azunyanを用意したくないし、
\$peroperoの空配列の変数も事前に用意したくないし、
[]で繋ぎ合わせたくないという反骨心が生まれてしまいましたッ!!
:fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire:

yieldしてみようッ!

yield_chunk.php
$peropero = iterator_to_array((function ($values) {
    while (count($values)) {
        yield array_splice($values, 0, 2);
        if (count($values)) yield array_splice($values, 0, 3);
    }
})(range(0, 10)));

var_dump(var_dump);

$peroperoに随時追加しないようにするのであれば、2個、3個……というchunkの結果を返す関数を作ればいいのでは?
けど関数だと結局、内部で変数を定義して処理しないといけなさそうだな……ならiteratorにして、結果を配列として受け取るようにしてしまえばいいのでは?という発想から誕生したコードになります。

これでも分割はできるんですが、whileの中で条件分岐ができなくなってしまったため、
yieldが2段階構成+if文が必要になるし、行も増えてしまうというイマイチな作りに。

行は減らしたいし、ifも書きたくないッ!

chunk_splice_merge.php
$peropero = call_user_func_array("array_merge", array_map(function($target) {
    return array_filter([array_splice($target, 0, 2), $target]);
}, array_chunk(range(0, 10), 5)));

var_dump($peropero);

行は減らしたいし、ifも書きたくないという贅沢な条件を満たしてみました。

2個、3個……という流れにするんであれば……
まず5個ずつに分割して、それを更に2個、3個に分割して、最終的にflatすれば良くないかという結論に。

flatする関数が生のphpでは存在しないという事実に心が折れかけましたが、
javascriptでいうスプレッド演算子的なのがあれば、array_mergeで2次元を1次元に落とせるのではと。
call_user_func_arrayの存在を思い出して、array_mergeで呼んであげています。

yieldの時に問題になったif文はarray_filterを実行することで取り除くようにしています。

結論ッ!

こんな見にくい処理をprに出したら怒られてしまうので、最初からシンプルに書いた処理にしておきましょう。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0