mochikoAsTechのdig日記

当方好きなコマンドはdigです!お友達から!!よろしくお願いします!!!

PHPでexplodeの後にarray_filterも通す理由を推察してみた

gistでPHPのコードを読んでいたらこんな個所があった。

$array = array_filter(explode(' ', $value)); 

$value には aaa bbb ccc みたいなテキストが入ってる。なので explode をつかって $value をスペースごとに分割して配列にするところまでは分かる。(explode については PHP: explode - Manual を参照)

こんな感じのコードを書いて、

<?php
$value = 'aaa bbb ccc';
$array = explode(' ', $value);
var_dump($array);

実行するとこうなるんだよね。わかる。 aaa bbb cccexplode で分割されて配列になった。

array(3) {
  [0]=>
  string(3) "aaa"
  [1]=>
  string(3) "bbb"
  [2]=>
  string(3) "ccc"
}

でもこれにさらに array_filter かけても、

<?php
$value = 'aaa bbb ccc';
$array = array_filter(explode(' ', $value));
var_dump($array);

実行結果はまったく同じ…んんん? array_filter なにしてるんだ…?( array_filter についてはこちら PHP: array_filter - Manual を参照)

$ php test.php 
array(3) {
  [0]=>
  string(3) "aaa"
  [1]=>
  string(3) "bbb"
  [2]=>
  string(3) "ccc"
}

array_filter って 第2引数に「奇数だったらtrueを返すメソッド」みたいなのを指定して、配列の中から奇数の要素だけをフィルタリングする 的なメソッドだと思ってたので、そもそも第2引数が指定されてないと何してるの…?と。

うーんうーんと考えた結果、恐らく次の2つのケースのときに array_filter が役に立つから使ってるんじゃないかな?と推察したので書いておく。

ケース1. $value が空文字だったときに empty の結果が変わる

次のように $value が空文字だった場合、

<?php
$value = '';

$array = explode(' ', $value);
var_dump($array);
var_dump(empty($array));

$array = array_filter(explode(' ', $value));
var_dump($array);
var_dump(empty($array));

explode だけだと配列に「値が空の要素」が1件入るけど、 array_filter を組み合わせれば要素は0件になる。

array(1) {
  [0]=>
  string(0) ""
}
bool(false)

array(0) {
}
bool(true)

こういうケースなら empty で空かどうかチェックしたときの結果が truefalse で分かれるので、 array_filter がいる意味わかるー。( empty についてはこちら PHP: empty - Manual を参照)

ケース2. $value にスペースが沢山あったときに詰められる

あとは aaa bbb ccc みたいに $value にスペースがたくさんあったとき! こういうときも explode だけだと要素数が7つになっちゃうけど、array_filter を通せばフィルタリングされて値のある3つだけになる。

<?php
$value = ' aaa  bbb   ccc';

$array = explode(' ', $value);
var_dump($array);
var_dump(count($array));

$array = array_filter(explode(' ', $value));
var_dump($array);
var_dump(count($array));
array(7) {
  [0]=>
  string(0) ""
  [1]=>
  string(3) "aaa"
  [2]=>
  string(0) ""
  [3]=>
  string(3) "bbb"
  [4]=>
  string(0) ""
  [5]=>
  string(0) ""
  [6]=>
  string(3) "ccc"
}
int(7)

array(3) {
  [1]=>
  string(3) "aaa"
  [3]=>
  string(3) "bbb"
  [6]=>
  string(3) "ccc"
}
int(3)

こういうケースでも array_filter は有用そう!

ただし falsenull があるときには要注意

explode で配列にしたときは、要素はすべて「文字列」として値に入るので、例えば -1 false null を渡した際に、

<?php
$value = '-1 false null';

$array = explode(' ', $value);
var_dump($array);

$array = array_filter(explode(' ', $value));
var_dump($array);

こんな感じで array_filter を通しても全く問題ないのですが、

array(3) {
  [0]=>
  string(2) "-1"
  [1]=>
  string(5) "false"
  [2]=>
  string(4) "null"
}

array(3) {
  [0]=>
  string(2) "-1"
  [1]=>
  string(5) "false"
  [2]=>
  string(4) "null"
}

配列に null やbooleanの false が入る場合は注意が必要そう。

<?php
$value = [ -1, false, null ];
var_dump($value);

$array = array_filter($value);
var_dump($array);

実行してみると、こんな感じでさらっと falsenull の要素がフィルタリングされて消えたー。

array(3) {
  [0]=>
  int(-1)
  [1]=>
  bool(false)
  [2]=>
  NULL
}

array(1) {
  [0]=>
  int(-1)
}

-1 みたいなの負の数は消えないんだね。なるほど。

こういう「人が書いたコードの意図や、どんなケースを想定しているのかを考える」のは楽しいなー。

なお上記は CentOS 6.10PHP 5.6.40CLI環境で確認しました。