Skip to content

[PHP]array_filterで配列から必要な値だけ抜き出す

Posted on:January 9, 2019 at 03:19 PM

今日 UnitTest の実装を考えてたんだけど、素直にやると全部ぶん回すような処理になりそうな気配があった。なので、「そういえば PHP にもフィルターかけれるようなのあったよな?」と思い出し、array_filterを使った実装で UnitTest を書いた。

忘れないうちに備忘録。

公式マニュアル

PHP: array_filter - Manual

公式には以下のコードがサンプルとして載っている。

<?php
function odd($var)
{
    // 渡された整数が奇数かどうかを返します
    return($var & 1);
}

function even($var)
{
    // 渡された整数が偶数かどうかを返します
    return(!($var & 1));
}

$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);

echo "Odd :\n";
print_r(array_filter($array1, "odd"));
echo "Even:\n";
print_r(array_filter($array2, "even"));

お、、、おう??

これ、正直に言ってめっちゃわかりにくい。なんで第二引数がstringなの?とか、functionには何が引数として渡ってるの?とかいう部分が読み取りづらい(※個人の感想です)。

サンプルコード改

なのでこれをクロージャで書いてあげると、読み取りやすくなる(と思う)。

<?php
$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);

echo "Odd :\n";
print_r(array_filter($array1, function ($arr) {
    return($arr & 1);
}));
echo "Even:\n";
print_r(array_filter($array2, function ($arr) {
    return(!($arr & 1));
}));

クロージャーの引数$arrには、$array1もしくは$array2の値が一つづつ渡ってくる(気になる方はvar_dumpなどで出力してみて)ので、$array1なら 1,2,3,4,5 が渡ってくるし、$array2なら 6,7,8,9,10,11,12 が渡ってくる。

クロージャーにあまり馴染みがなければ逆に難しいのかもしれない(PHP でクロージャーってそんな書かないもんね…)が、僕的にはこっちの書き方の方が馴染むし、見通しもよく感じる。

クロージャーについては、公式マニュアルがあるので、合わせて読むと理解が深まるはずだ。

PHP: 無名関数 - Manual

もちろん、普通のクロージャーと同じく、こういう場合でもuse文を書くことで変数を持ってくることができる(サンプルがしょぼくて申し訳ない)。

<?php
$val = 10;
$array = array(6, 7, 8, 9, 10, 11, 12);

echo "Same :\n";
print_r(array_filter($array, function ($arr) use ($val) {
    return($arr === $val);
}));

こうやってまとめたから、きっともう忘れない、はず(少なくともブログに書いたことは忘れない)。

余談

直近で Flutter/Dart のプロジェクトをやっていたこともあって、こういう functional っぽい感じが好きになった。