Home > Laravel | PHP > PHP で配列を走査して処理するのは、for / foreach だけじゃない

PHP で配列を走査して処理するのは、for / foreach だけじゃない

この記事の所要時間: 918

PHP で配列の要素にアクセスして、処理を行うには、for や foreach を使うのがおなじみです。

php-logo

この方法でも良いのですが、PHPには、それ以外にも配列を走査する関数やライブラリがあります。ここでは、配列を走査して処理を行う方法を見てみましょう。

サンプル仕様

このエントリで以下の配列を処理対象とします。array.phpで保存されている想定です。

<?php
return [
    [
        'id' => 1,
        'year' => 1993,
        'name' => 'Harada',
    ],
    [
        'id' => 2,
        'year' => 2001,
        'name' => 'Kato',
    ],
    [
        'id' => 3,
        'year' => 2009,
        'name' => 'Aoyama',
    ]
];

この配列について処理を行います。

  • 配列内に連想配列が格納されており、nameyearというキーを持つ
  • yearが、2000以上の要素のみ、結果配列に格納する
  • 結果配列には、nameyearを連結した文字列を格納する

求める結果は、以下になります。

array(2) {
  [0] =>
  string(8) "2001Kato"
  [1] =>
  string(10) "2009Aoyama"
}

foreach を使う

まずは、foreach を使う方法です。よくある手続き的なPHPコードですね。foreachで配列を回して、yearが2000以上の場合だけ、結果配列に値を入れています。

<?php
$array = include('array.php');

$result = [];

foreach ($array as $v) {
    if ($v['year'] <  2000) {
        continue;
    }

    $result[] = $v['year'] . $v['name'];
}

var_dump($result);

array系関数を使う

次に、filter と map を使って、実装します。PHP には、array_maparray_filter関数があるので、これを使います。

実装は下記になります。array_filterarray_mapを使うので、それぞれ配列の要素をフィルタリングする、要素に処理を行い、結果配列を格納するといった意図がより明確になります。

ただ、array_fileterarray_mapで引数の順序が異なるのと、2 行に分かれており、中間の結果を保持する一時変数が必要になるのが難点です。

<?php
$array = include('array.php');

$tmp = array_filter($array, function($v) {
    return $v['year'] >= 2000;
});

$result = array_map(function($v) {
    return $v['year'] . $v['name'] ;
}, $tmp);

var_dump($result);

試しに 1 行にまとめると下記になります。一見良さそうですが、このコードをぱっと見て、array_filterが先に適用されるのと認識できるでしょうか。

$result = array_map(function($v) {
    return $v['year'] . $v['name'] ;
}, array_filter($array, function($v) {
    return $v['year'] >= 2000;
}));

Laravel(Illuminate\Supportパッケージ)を使う

filter / map を使う別の例として、Illuminate\Supportパッケージ のIlluminate\Support\Collectionクラスを使います。

https://github.com/illuminate/support

Illuminate\Support パッケージは、Laravel を構成しているパッケージの一つで、フレームワークを使わずとも、このパッケージ単体でも利用することができます。

インストールするには、composer.jsonに以下のように指定して、composer installもしくはcomposer updateを実行します。

{
    "require": {
        "illuminate/support": "~4.2"
    }
}

Illuminate\Support\Collectionを使うことで、メソッドチェインで配列を操作することができます。

実装すると下記のようになります。filterメソッドでフィルタリングを行い、その結果配列に対してmapメソッドを実行して、結果配列の要素を作成していることが分かります。

<?php
use IlluminateSupportCollection;

require_once __DIR__ . '/vendor/autoload.php';

$array = include('array.php');

$result = Collection::make($array)->filter(function ($v) {
    return $v['year'] >= 2000;      // filter

})->map(function ($v) {
    return $v['year'] . $v['name']; // map

})->toArray();

var_dump($result);

Ginq を使う

Illuminate\Support\Collectionと似た機能を持つライブラリに、Ginq があります。こちらもメソッドチェインで配列への操作を行うことができます。

https://github.com/akanehara/ginq

インストールするには、composer.jsonに以下のように指定して、composer installもしくはcomposer updateを実行します。

{
    "require": {
        "ginq/ginq": "~0.1"
    }
}

Ginq を使って、実装すると、下記のようになります。配列を取り込むところ以外は、Illuminate\Support\Collectionと全く一緒になりました。

<?php
require_once __DIR__ . '/vendor/autoload.php';

$array = include('array.php');

$result = Ginq::from($array)->filter(function ($v) {
    return $v['year'] >= 2000;      // filter

})->map(function ($v) {
    return $v['year'] . $v['name']; // map

})->toArray();

var_dump($result);

さいごに

4 つのパターンで配列を走査して、結果配列を求めるという処理を書いてみました。

foreach は、配列の要素を走査していくという汎用的な役割なので、そのループの中で様々な処理を書くことができます。一方、array系関数やライブラリは、それぞれのメソッドで用途や目的が決まっているので、どのような処理を行い、結果、どのような解を求めているのが分かりやすいです。

また、filter や map という概念は、多くのプログラミング言語で利用されており、こうした概念をおさえておくと、別の言語でコードを書いたり、読んだりする際に、意図を汲むことができ理解しやすくなります。

foreach で書くことがダメだというわけではなく、それ以外の書き方が、PHPにもあるということを知っておくということが大事ですね。

Illuminate\Support\Collection と Ginq

Illuminate\Support\Collection と Ginq は、Linq to Object ライクなインターフェースを持ち、実際に使い方も似ています。

ただ、この2つで大きく違うのが、評価のタイミングです。

Illuminate\Support\Collection は、mapメソッドを実行したタイミングで即時に評価され、処理が行われます。

一方、Ginqは、遅延評価となっており、mapメソッドを実行してもすぐに map 処理が行われません。このエントリの例では、toArray()が実行されたタイミングで、はじめて map 処理が行われます。

実際に利用する際は、この評価タイミングの違いは、意識しておく必要があります。

参考

迫り来る「forおじさん」と呼ばれる時代

Pocket

follow us in feedly

Home > Laravel | PHP > PHP で配列を走査して処理するのは、for / foreach だけじゃない

検索
フィード
メタ情報

Return to page top