はじめに
Advent Calendarに参加するのは初めてです。
普段投稿している記事より多くの方に見られるかと思いますので、緊張しますね・・・
ちなみに自分のPHP歴は1年半ほどで、実務経験に至っては異業種(事務職)から転職してちょうど4ヶ月経ったところです。
まだ新参者ですが、この視点が皆様のお役に立てば嬉しいです。
なぜ配列関数をテーマにしたのか?
YYPHP Advent Calendar 2018のsuinさんの記事に影響を受けました。
こちらに学びのガイドラインとして、PHPの公式マニュアルであるphp.netに関する記事が紹介されています。
さらにこの中で、YYPHP参加者の意見として「配列系の関数は全て目を通すと信じられないほどはかどる」
との紹介がありますが、これに共感したからです。
私は既存のコードを読むのも自分でコードを書くのも大変時間がかかります。やばいです。そして配列が登場すると値の受け渡し、処理の流れが途端に追い難くなります。
なので、配列関数がその解決の糸口になるのではと思い、今回の記事のテーマにしました。
php.netの配列関数
現在、php.net 配列関数では82個
の配列関数が紹介されています。
多いのか少ないのか正直わかりません。
今回の執筆にあたり、各配列関数の説明〜例(最初の例だけ)
を読んでみました。完璧に覚えるのは不可能なので、自分の中にインデックスを作成するイメージです。
さらに関数の役割を分類できれば使いやすいのではと思い、私の独断と偏見で分類しました。
なお、配列関数全てを分類したわけではありません。分類したのは関数の役割です。(情報量が多すぎると概要すら掴めなくなる恐れがあるので・・・)
紹介する配列関数も、分類した中で一番簡単に説明できるものを選びました。
では、始めます。
編集系
これらの機能が、単独または組み合わされて動く関数です。(配列関数の解説はphp.net 配列関数から抜粋しました。)
- 追加
- 削除
- 置換
- 分割
- 抽出
array_push
一つ以上の要素を配列の最後に追加する。(追加)
追加する要素が1つの場合は、$fruits[] = "banana";
の書き方が勧められています。(by公式)
$fruits = array('apple', 'orange');
var_dump(array_push($fruits, "banana"));
// 出力結果: int(3)
var_dump($fruits);
// 出力結果:
// array(3) {
// [0]=>
// string(5) "apple"
// [1]=>
// string(6) "orange"
// [2]=>
// string(6) "banana"
// }
array_pop
配列の末尾から要素を取り除く。(削除)
$fruits = array('apple', 'orange', 'banana');
var_dump(array_pop($fruits));
// 出力結果: string(6) "banana"
var_dump($fruits);
// 出力結果:
// array(2) {
// [0]=>
// string(5) "apple"
// [1]=>
// string(6) "orange"
// }
array_splice
配列の一部を削除し、他の要素で置換する。(削除・置換)
$fruits = array('apple', 'orange', 'banana');
var_dump(array_splice($fruits, 2, 1, "lemon"));
// 出力結果:
// array(1) {
// [0]=>
// string(6) "banana"
// }
var_dump($fruits);
// 出力結果:
// array(3) {
// [0]=>
// string(5) "apple"
// [1]=>
// string(6) "orange"
// [2]=>
// string(5) "lemon"
// }
array_chunk
配列を分割する。(分割)
$fruits = array('apple', 'orange', 'banana', 'lemon', 'peach');
var_dump(array_chunk($fruits, 2));
// 出力結果:
// array(3) {
// [0]=>
// array(2) {
// [0]=>
// string(5) "apple"
// [1]=>
// string(6) "orange"
// }
// [1]=>
// array(2) {
// [0]=>
// string(6) "banana"
// [1]=>
// string(5) "lemon"
// }
// [2]=>
// array(1) {
// [0]=>
// string(5) "peach"
// }
// }
array_filter
コールバック関数を使用して、配列の要素をフィルタリングする。(抽出)
function number_check($num)
{
if ($num % 2 === 1) {
return true;
} else {
return false;
}
}
$number = array(1, 2, 3, 4, 5);
var_dump(array_filter($number, "number_check"));
// 出力結果:
// array(3) {
// [0]=>
// int(1)
// [2]=>
// int(3)
// [4]=>
// int(5)
// }
array_column
入力配列から単一のカラムの値を返す。(抽出)
$members = array(
array(
'name' => 'John',
'sex' => 'male',
'age' => 35,
),
array(
'name' => 'Kate',
'sex' => 'female',
'age' => 30,
),
array(
'name' => 'Peter',
'sex' => 'male',
'age' => 25,
),
);
var_dump(array_column($members, 'name'));
// 出力結果:
// array(3) {
// [0]=>
// string(4) "John"
// [1]=>
// string(4) "Kate"
// [2]=>
// string(5) "Peter"
// }
情報取得系
count
変数に含まれるすべての要素、 あるいはオブジェクトに含まれる何かの数を数える。
$number = array(1, 2, 3, 4);
var_dump(count($number));
// 出力結果: int(4)
検索系
in_array
配列に値があるかチェックする。
$fruits = array('apple', 'orange', 'banana', 'lemon', 'peach');
var_dump(in_array("apple", $fruits));
// 出力結果: bool(true)
array_search
指定した値を配列で検索し、見つかった場合に対応する最初のキーを返す。
$fruits = array('apple', 'orange', 'banana', 'lemon', 'peach');
var_dump(array_search("lemon", $fruits));
// 出力結果: int(3)
ソート系
sort
配列をソートする。
$number = array(1, 2, 3);
$fruits = array('apple', 'orange', 'banana');
var_dump(sort($number));
// 出力結果: bool(true)
var_dump(sort($fruits));
// 出力結果: bool(true)
foreach ($number as $num) {
echo $num."\n";
}
// 出力結果:
// 1
// 2
// 3
foreach ($fruits as $fruit) {
echo $fruit."\n";
}
// 出力結果:
// apple
// banana
// orange
複数配列系
比較
array_diff
配列の差を計算する。
$array1 = array("a" => "apple", "c" => "orange", "banana", "lemon", "plum");
$array2 = array("b" => "apple", "orange", "c" => "banana", "lemon", "peach");
$result = array_diff($array1, $array2);
echo "<pre>";
var_dump($result);
echo "</pre>";
// 出力結果:
// array(1) {
// [2]=>
// string(4) "plum"
// }
array_intersect
配列の共通項を計算する。
$array1 = array("a" => "apple", "c" => "orange", "banana", "lemon", "plum");
$array2 = array("b" => "apple", "orange", "c" => "banana", "lemon", "peach");
$result = array_intersect($array1, $array2);
echo "<pre>";
var_dump($result);
echo "</pre>";
// 出力結果:
// array(4) {
// ["a"]=>
// string(5) "apple"
// ["c"]=>
// string(6) "orange"
// [0]=>
// string(6) "banana"
// [1]=>
// string(5) "lemon"
// }
結合
array_merge
ひとつまたは複数の配列をマージする。
$array1 = array("a" => "apple", "b" => "orange", "banana", "lemon");
$array2 = array("b" => "apple", "c" => "banana","orange", "lemon", "peach");
$result = array_merge($array1, $array2);
var_dump($result);
// 出力結果:
// array(8) {
// ["a"]=>
// string(5) "apple"
// ["b"]=>
// string(5) "apple"
// [0]=>
// string(6) "banana"
// [1]=>
// string(5) "lemon"
// ["c"]=>
// string(6) "banana"
// [2]=>
// string(6) "orange"
// [3]=>
// string(5) "lemon"
// [4]=>
// string(5) "peach"
// }
その他
値同士の計算
array_sum
配列の中の値の合計を計算する。
$number = array(1, 2, 3, 4);
echo array_sum($number);
// 出力結果: 10
array_product
配列の値の積を計算する。
$number = array(1, 2, 3, 4);
echo array_product($number);
// 出力結果: 24
配列・変数間の変換
list
配列と同様の形式で、複数の変数への代入を行う。
$member = array('John', 'male', 35);
list($name, $sex, $age) = $member;
echo "$name, $sex, $age";
// 出力結果: John, male, 35
compact
変数名とその値から配列を作成する。
$name = "John";
$sex = "male";
$age = 35;
$member = compact("name", "sex", "age");
echo "<pre>";
var_dump($member);
echo "</pre>";
// 出力結果:
// array(3) {
// ["name"]=>
// string(4) "John"
// ["sex"]=>
// string(4) "male"
// ["age"]=>
// int(35)
// }
ポインタ移動
ポインタを移動させる。
ポインタは、PHPのバージョンによってforeachにおける挙動が異なるそうです。
$fruits = array('apple', 'orange', 'banana', 'lemon', 'peach');
$fruit = current($fruits); // $fruit = 'apple';
$fruit = next($fruits); // $fruit = 'orange';
$fruit = prev($fruits); // $fruit = 'apple';
$fruit = end($fruits); // $fruit = 'peach';
$fruit = reset($fruits); // $fruit = 'apple';
注目したこと
初学者向けですが、ここに注目すると良いかもしれません。
対象は値か、キー(添字)か、その両方か
関数によって対象とするものが違います
間違った関数を使用すると、意図しない結果になってしまいます。
- array_diff(値だけを確認して、配列の差を計算する。)
- array_diff_key(キーだけを確認して、配列の差を計算する。)
- array_diff_assoc(キーと値の両方を確認して、配列の差を計算する。)
似た名前が存在する関数は要注意です。
返り値と配列自身の変化
配列の末尾から要素を取り除くarray_pop
をもう一度見てみます。
この場合、返り値は削除した要素banana
になり、配列$fruits
自身もその要素が削除されます。
$fruits = array('apple', 'orange', 'banana');
var_dump(array_pop($fruits));
// 出力結果: string(6) "banana"
var_dump($fruits);
// 出力結果:
// array(2) {
// [0]=>
// string(5) "apple"
// [1]=>
// string(6) "orange"
// }
今度は配列を分割するarray_chunk
を見てみます。
こちらは、返り値に関数を使用した後の配列がそのまま入っています。
元の配列$fruit
自身に変化はありません。(下記のコードには記載されていませんが。)
$fruits = array('apple', 'orange', 'banana', 'lemon', 'peach');
var_dump(array_chunk($fruits, 2));
// 出力結果:
// array(3) {
// [0]=>
// array(2) {
// [0]=>
// string(5) "apple"
// [1]=>
// string(6) "orange"
// }
// [1]=>
// array(2) {
// [0]=>
// string(6) "banana"
// [1]=>
// string(5) "lemon"
// }
// [2]=>
// array(1) {
// [0]=>
// string(5) "peach"
// }
// }
詳細はphp.net 配列関数の説明
と返り値
の項目に説明されていますので、読むことを強くお勧めします。
実際に動かしてみる
- 配列関数の
例
をコピーして、実際に動かしてみます。 - さらに値や引数を変えて遊んでみます。
- さらに随所で
var_dump
すると処理の流れがわかりやすいです。
配列関数に限らずですが(`・ω・´)
関数によっては、配列の値の型によって動作が変わるものがあります。
var_dump
は配列や変数の内容確認はもちろんのこと、それらの型
をチェックできるので、習慣にしておくと良いです。
コールバック関数がよく使われる
コールバック関数が使える配列関数も多いです。内容はユーザーが定義できるので、関数のカスタマイズができます。
名前にu
が入る関数が多いです。もちろんそれ以外にも存在します。
- array_udiff(データの比較にコールバック関数を用い、配列の差を計算する。)
- array_walk(配列の全ての要素にユーザー定義の関数を適用する。)
- usort(ユーザー定義の比較関数を使用して、配列を値でソートする。)
コールバック関数はcallable
という型(タイプヒント)で表されています。関数の引数に、文字列としてコールバック関数を与えます。
実はこの記事を書いていて、初めて存在を知りました・・・
再帰処理がされているかどうか
まず、再帰処理がうまく説明できません。
・・・・・・イメージはだいたい掴めたかも。
実際に、再帰処理の有無で動作が違うarray_merge_recursive
とarray_merge
を見比べてみます。
$array1 = array("color" => array("favorite" => "red"), 5);
$array2 = array(10, "color" => array("favorite" => "green", "blue"));
$result1 = array_merge_recursive($array1, $array2);
var_dump($result1);
// 出力結果:
// array(3) {
// ["color"]=>
// array(2) {
// ["favorite"]=>
// array(2) {
// [0]=>
// string(3) "red"
// [1]=>
// string(5) "green"
// }
// [0]=>
// string(4) "blue"
// }
// [0]=>
// int(5)
// [1]=>
// int(10)
// }
$result2 = array_merge($array1, $array2);
var_dump($result2);
// 出力結果:
// array(3) {
// ["color"]=>
// array(2) {
// ["favorite"]=>
// string(5) "green"
// [0]=>
// string(4) "blue"
// }
// [0]=>
// int(5)
// [1]=>
// int(10)
// }
多次元配列になっているcolor
の部分に注目です。
再帰処理がされている場合は、$array1(マージ元)のred
、$array2(マージ先)のgreen, blue
が全て存在していますが、そうでない場合はマージ先の値に上書きされ、マージ元である$array1の値red
が消えています。
・・・・・・。
まだ理解がふわふわしているので、この辺りは実際にコード書いて試しながら慣れていこうと思います。
フレームワークにもあるよ
フレームワークにも独自の関数が定義されています。ヘルパ関数
です。
力が尽きかけているので、1つだけ使ってみます。
Laravelのヘルパ関数
array_get
指定された値を「ドット」記法で指定された値を深くネストされた配列から取得する。
$array = ['member' => ['John' => ['age' => 35]]];
$age = array_get($array, 'member.John.age');
var_dump($age);
// 出力結果: int(35)
多次元配列を対象とする関数が多そうですね。
公式サイトもかなり充実してます。
PHPとフレームワークに同じ機能を持つ関数がある場合、どちらを使用すべきか判断できると良いのですが!
参考記事
配列関数を分類した記事はあまり見かけませんでしたが、以下に参考記事を紹介します。
おわりに
流石に、配列関数82個は読むのが大変でした。(流し読みでも!)
しかし、「配列関数でこんなことができる」は、「配列はこうやって使うことが多い」に繋がっているかと思います。
コードを掲載した関数は、全て自分の端末で手を動かして確認したものです。今回それを記事としてアウトプットし皆様に読んでいただき、素敵な思い出にもなりました。
ここまでお読みいただき本当にありがとうございます。
皆様良いクリスマスを(^ ^)
明日12/6は@kasyuuさんです。
何とかタスキはつなげました・・・よろしくお願いします!