9
8

More than 3 years have passed since last update.

【PHP 初級】配列おさらい➁ ~取得・検索・その他~

Last updated at Posted at 2021-01-23

【PHP 初級】配列おさらい➀ ~宣言・初期化・追加・結合・削除~の続きです。
今回は配列から値を取得、検索する方法など、もう少し実務的な内容をまとめます。

値の取得

配列から値を取り出す色んな方法を見てみます。

キーを指定して値を取り出す

どの言語も同じように、数値やキーを指定して値を取り出します。

php > $fruits = ['apple', 'grape', 'banana'];

php > var_export($fruits[0]);
'apple'
php > $colors = ['C1' => 'red', 'C2' => 'purple', 'C3' => 'green'];

php > var_export($colors['C1']);
'red'

すべての値を取り出す

array_values

array_values (配列)
戻り値:配列

array_valuesは配列のすべての値を取り出し、数値のインデックス番号を付けた配列を返します。
【PHP 初級】配列おさらい➀ ~宣言・初期化・追加・結合・削除~で紹介したように、配列の値の削除を行った後、インデックス番号を詰め直すのに利用したりします。
またarray_valuesに連想配列を渡せば、配列に変換することが出来ます。

php > $colors = ['C1' => 'red', 'C2' => 'purple', 'C3' => 'green'];

php > var_export(array_values($colors));
array (
  0 => 'red',
  1 => 'purple',
  2 => 'green',
)

多次元配列からキーを指定して値を取り出す

array_column

array_column (配列, 指定するキー)
戻り値:配列

array_columnは個人的にかなり良く使うメソッドなので、ぜひ使い方を身に付けてみてください。
array_columnは多次元配列のキーを指定し、全ての値を配列で返します。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// 学生の名前を取得
php > $students_name = array_column($students, 'name');
php > var_export($students_name);
array (
  0 => 'tanaka',
  1 => 'yamamoto',
  2 => 'honda',
  3 => 'inoue',
)

また第3引数を指定して、特定の値をキーにした多次元配列を生成することもできます。

array_column (配列, 指定するキー、新しい配列のキーとして指定するキー)
戻り値:配列

言葉が分かりづらいですが、例を見ればすぐに理解できると思います。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に名前を取得する
php > $name_by_class = array_column($students, 'name', 'class');
php > var_export($name_by_class);
array (
  1 => 'honda',
  2 => 'yamamoto',
  3 => 'inoue',
)

注意点はキーが重複する場合、後ろの値で上書きされます。
そのため、クラス1はhondaくんが取得されます。

名前だけでなく、学生の情報が全て取得したい場合は第2引数にnullを指定します。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に学生の情報を取得する
php > $student_by_class = array_column($students, null, 'class');
php > var_export($student_by_class);
array (
  1 =>
  array (
    'class' => 1,
    'name' => 'honda',
    'age' => 16,
  ),
  2 =>
  array (
    'class' => 2,
    'name' => 'yamamoto',
    'age' => 16,
  ),
  3 =>
  array (
    'class' => 3,
    'name' => 'inoue',
    'age' => 17,
  ),
)

こちらもクラス1は重複するため、hondaくんの情報のみ取得されています。

多次元配列のキーでグルーピングする

上書きしないでクラス毎の全員の情報が取得したい場合は、次のような自作メソッドが必要になります。

public function groupBy($list, $key) {
    $ret = array();
    if (is_array($list)) {
        foreach ($list as $val) {
            $ret[$val[$key]][] = $val;
        }
    }

    return $ret;
}

Utilメソッドとして定義し、どこからでも使えるようにしたら良いです。
グルーピングした結果は以下のようになります。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に学生をグループ化する
php > $group_by_class = groupBy($students, 'class');
php > var_export($group_by_class);
array (
  1 =>
  array (
    0 =>
    array (
      'class' => 1,
      'name' => 'tanaka',
      'age' => 15,
    ),
    1 =>
    array (
      'class' => 1,
      'name' => 'honda',
      'age' => 16,
    ),
  ),
  2 =>
  array (
    0 =>
    array (
      'class' => 2,
      'name' => 'yamamoto',
      'age' => 16,
    ),
  ),
  3 =>
  array (
    0 =>
    array (
      'class' => 3,
      'name' => 'inoue',
      'age' => 17,
    ),
  ),
)

キーの取得

次はキーを取得する方法を見てみましょう。

配列の全てのキーを取得する

array_keys

array_keys (配列)
戻り値:配列

引数に渡した配列の全てのキーを配列にて返します。

php > $fruits_color = [
php >     'apple' => 'red',
php >     'banana' => 'yellow',
php >     'orange' => 'orange',
php >     'cherry' => 'red',
php > ];

php > var_export(array_keys($fruits_color));
array (
  0 => 'apple',
  1 => 'banana',
  2 => 'orange',
  3 => 'cherry',
)

値を指定してキーを取得する

array_keys

array_keys (配列, 指定する値, 型比較を行うか)
戻り値:配列

指定した値に該当するキーを取得するにはarray_keysに第2引数を渡して使用します。
第3引数には値を検索する際に厳密な比較===を行うかどうかをtrue,falseで指定します。
常にtrueを指定することをお勧めします。

php > $fruits_color = [
php >     'apple' => 'red',
php >     'banana' => 'yellow',
php >     'orange' => 'orange',
php >     'cherry' => 'red',
php > ];

php > $red_fruits = array_keys($fruits_color, 'red', true);
php > var_export($red_fruits);
array (
  0 => 'apple',
  1 => 'cherry',
)

もし第3引数にtrueを指定しない場合、以下のような想定外の動作をする可能性があります。

php > $numbers = [
php >     'zero' => 0,
php >     'one' => 1,
php >     'two' => 2,
php > ];

// 何も取得されないと思いきや、'zero'が取得される
php > $number = array_keys($numbers, 'a');
php > var_export($number);
array (
  0 => 'zero',
)

第3引数を指定しないと値の検索に緩やかな比較==を行います。
PHPは型が異なる値同士を比較する際に、暗黙的な型変換を行います。
そのため数値と文字列を比較しようとすると、文字列は0に変換されてしまいます。

php > var_export((int) 'a');
0

なので上記のように第2引数に'a'を指定しても、実際には0に変換されてしまうので、'zero'が取得されてしまうのです。
このような想定外の動作はバグを引き起こす可能性があるため、避けるべきでしょう。

値の検索

値を指定して存在するか検索する

array_search

array_search(検索する値, 配列, 型比較を行うか)
戻り値:キーもしくはfalse

値が見つかった場合、該当のキーを返します。
見つからなかった場合はfalseを返します。

array_keysは値を指定した場合、該当するキーを全て配列で返しますが、array_searchは1つのキーを数値か文字列にて返します。
そのため1つ以上の値が見つかる場合は先に見つかった方のキーを返します。

php > $foods = ['ramen', 'sushi', 'curry', 'udon', 'karaage', 'sushi'];

// 寿司を検索。寿司は2つあるため、前方のキーが取得される。
php > $sushi_key = array_search('sushi', $foods, true);
php > var_export($sushi_key);
1

// ピザを検索。値が見つからないためfalseを返す。
php > $pizza_key = array_search('pizza', $foods, true);
php > var_export($pizza_key);
false

array_searchも第3引数にtrueを指定して厳密な比較を行うようにしましょう。

in_array

in_array(検索する値, 配列, 型比較を行うか)
戻り値:trueもしくはfalse

使い方はarray_searchと同じですが、値が見つかった場合にキーではなくtrueを返します。
第3引数にはもちろんtrueを指定します。

php > $foods = ['ramen', 'sushi', 'curry', 'udon', 'karaage', 'sushi'];

php > $sushi_key = in_array('sushi', $foods, true);
php > var_export($sushi_key);
true

php > $pizza_key = in_array('pizza', $foods, true);
php > var_export($pizza_key);
false

array_searchin_arrayの使い分けは、
値を検索して存在する場合、その値を用いて何らかの処理をしたい時はarray_search

$key = array_search('val', $list, true);
if ($key !== false) {
    $value = $list[$key];
    ... // 値を使って処理を行う
}

値を検索して存在するかしないかで何らかの処理をしたい場合はin_arrayを使うイメージです。

if (in_array('val', $list, true)) {
    ... // 存在する場合の処理
} else {
    ... // 存在しない場合の処理
}

キーの検索

キーを指定して存在するか検索する

array_key_exists

array_key_exists (検索するキー, 配列)
戻り値:trueもしくはfalse

第1引数に渡したキーが存在すればtrueを返します。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(array_key_exists('name', $fruits));
true
php > var_export(array_key_exists('price', $fruits));
false

issetemptyを使ってもarray_key_existsと同じようなことができます。

isset

isset (変数)
戻り値:trueもしくはfalse

変数が宣言されていて、かつnullでなければtrueを返します。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(isset($fruits['name']));
true
php > var_export(isset($fruits['price']));
false

empty

empty (変数)
戻り値:trueもしくはfalse

変数が宣言されていないか、空であればtrueを返します。
array_key_existissetとは逆にキーが存在しなければtrueを返します。
同じ使い方をしたい場合は必ず!を付けるようにしましょう。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(!empty($fruits['name']));
true
php > var_export(!empty($fruits['price']));
false

array_key_exists、isset、emptyの違い

array_key_existsはキーが定義されているかどうかのみを判断します。
issetはキーが定義されているか、また値がnullではないかを判断します。
emptyはキーが提起されているか、また値が空ではないかを判断します。

いくつかの違いをまとめると以下のようになります。

key/value array_key_exists isset !empty
'a' => undefined false false false
0 => NULL true false false
1 => '' true true false
2 => 0 true true false
3 => 'val' true true true
// array_key_exists
php > var_export(array_key_exists('a', $list));
false
php > var_export(array_key_exists(0, $list));
true
php > var_export(array_key_exists(1, $list));
true
php > var_export(array_key_exists(2, $list));
true
php > var_export(array_key_exists(3, $list));
true

// isset
php > var_export(isset($list['a']));
false
php > var_export(isset($list[0]));
false
php > var_export(isset($list[1]));
true
php > var_export(isset($list[2]));
true
php > var_export(isset($list[3]));
true

// empty
php > var_export(!empty($list['a']));
false
php > var_export(!empty($list[0]));
false
php > var_export(!empty($list[1]));
false
php > var_export(!empty($list[2]));
false
php > var_export(!empty($list[3]));
true

キーが存在するかチェックしたい場合はarray_key_existsを、
キーが存在して意味のある値が入っていることを確認したい場合はissetemptyを使いましょう。

その他、配列に関する色々

JAVAのstreamぽい書き方もできる

詳細は割愛しますが、JAVAのstreamのように配列の全要素を回しながら処理する色んな関数があります。
array_walk

array_walk (配列, コールバック関数, コールバック関数の引数)
戻り値:true

配列を回してコールバック関数の処理を行います。
コールバック関数に渡す第1引数は配列の値、第2引数は配列のキーになります。
コールバック関数で第3引数を使用したい場合はarray_walkに第3引数を指定します。
JAVAのstream.forEachみたいなイメージです。

array_filter

array_filter (配列, コールバック関数, モード)
戻り値:配列

配列を回してコールバック関数でフィルタリングした結果を配列で返します。
第3引数ではコールバック関数に何を引数として渡すかを指定します。
デフォルトだと配列の値を引数として渡します。
JAVAのstream.filterに値します。

array_map

array_map (コールバック関数, 配列...)
戻り値:配列

配列を回してコールバック関数の処理を行います。
コールバック関数の処理を通った結果を配列で返します。
コールバック関数に引数で渡す配列は複数指定することが出来ます。
JAVAのstream.mapに似ています。

最後の要素の後にはカンマを付ける

これは賛否両論があるようですが
1行で記述する場合は最後にカンマを付けない
複数行で技術する場合は最後にカンマを付ける
が一般的のようです。

PHP公式サイト

配列を一行で定義する場合は、ふつうは最後のカンマを省略します。
つまり、 array(1, 2) のほうが array(1, 2, ) よりおすすめだということです。
しかし複数行で定義する場合は、最後のカンマをつけることが一般的です。
そうしておけば、配列の最後に要素を追加するのが容易になるからです。

Zend framework

we encourage using a trailing comma for the last item in the array; this minimizes the impact of adding new items on successive lines, and helps to ensure no parse errors occur due to a missing comma.

$sampleArray = array(1, 2, 3, 'Zend', 'Studio'); // 最後にカンマを付けない
$sampleArray = array(
    1, 2, 3, 'Zend', 'Studio',
    $a, $b, $c,
    56.44, $d, 500, // 最後にカンマを付ける
);
9
8
0

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
9
8