【PHP 初級】配列おさらい➀ ～宣言・初期化・追加・結合・削除～

JAVAエンジニアの私が初めてPHPを使いながら気になったことなどを色々まとめてみました。
そのため、内容はPHP初心者向けになっております。

# PHPの配列
基本的にはJAVAの配列（Array）と同じ感じで使えますが、PHPにはJAVAで言うMapの概念がありません。
その代わりに`key=>value`の**連想配列**を使用します。

PHPでは配列をよく使うことになるため、配列を操作する数多くのメソッドが用意されています。
ここでは配列に関する基礎知識から色んなメソッドの使い方も見ていきます。

## 宣言
配列は`array()`か`[]`(※PHP5.4以降)で宣言します。
個人的には`[]`での宣言を好みます。

```php
php > $list1 = array();
php > $list2 = [];

// 値の確認はvar_dump, var_export, print_rなどを使います。
php > var_dump($list1);
array(0) {
}
php > print_r($list2);
Array
(
)
```

## 初期化
### 配列
配列の初期化は以下のように行います。

```php
php > $list1 = array(100, 200, 300);
// 代入する値の型は混在も可能です。数値、文字列、配列、オブジェクトなど
php > $list2 = [100, 'a', [], new stdClass];

php > var_export($list1);
array (
  0 => 100,
  1 => 200,
  2 => 300,
)
php > var_dump($list2);
array(4) {
  [0]=>
  int(100)
  [1]=>
  string(1) "a"
  [2]=>
  array(0) {
  }
  [3]=>
  object(stdClass)#1 (0) {
  }
}
```
### 連想配列
連想配列は`key=>value`の形で初期化します。

```php
php > $list3 = ['key1'=>100, 'key2'=>200, 'key3'=>300];

php > var_export($list3);
array (
  'key1' => 100,
  'key2' => 200,
  'key3' => 300,
)
```

## 値の追加
### 配列
配列に値を追加する場合は`[]`、`array_push`を使います。
#### []
[]は値を1つしか追加できません。
foreachなどループ内で値を追加する時によく使われます。

```php
php > $list1 = [100];
php > $list1[] = 200;

php > var_export($list1);
array (
  0 => 100,
  1 => 200,
)
```
#### array_push
https://www.php.net/manual/ja/function.array-push.php
>array_push (配列 , 追加する値...) 
>戻り値：追加後の配列のサイズ

`array_push`は複数の値を1度に追加することができます。

```php
php > $list1 = [];
php > array_push($list1, 'a', 'b', 'c');

php > var_export($list1);
array (
  0 => 'a',
  1 => 'b',
  2 => 'c',
)
```
### 連想配列
連想配列に値を追加する場合は`[]`を使います。
#### []
[]にキーを指定して値を追加します。

```php
php > $list1 = ['key1' => 100];
php > $list1['key2'] = 200;

php > var_export($list1);
array (
  'key1' => 100,
  'key2' => 200,
)
```

## 配列の結合
配列の結合には`+演算子`、`array_merge`、`array_merge_recursive`を使います。

### 配列
#### +演算子
同じインデックス番号の値は基となる前の配列の値が使われます。
それ以外の値は追加されて結合されます。

```php
php > $list1 = ['a', 'b'];
php > $list2 = $list1 + ['c', 'd', 'e'];

// インデックス'0', '1'は重複するため、前の'a', 'b'が使われます。
// インデックス'2'は基の配列には存在しないため、'e'が追加で結合されます。
php > var_export($list2);
array (
  0 => 'a',
  1 => 'b',
  2 => 'e',
)
```

#### array_merge
https://www.php.net/manual/ja/function.array-merge.php
>array_merge (結合する配列...)
>戻り値：結合した配列

配列の場合、インデックス番号が連番で追加されて結合されます。

```php
php > $list1 = ['a', 'b'];
php > $list2 = array_merge($list1, ['c', 'd', 'e']);

php > var_export($list2);
array (
  0 => 'a',
  1 => 'b',
  2 => 'c',
  3 => 'd',
  4 => 'e',
)
```

#### array_merge_recursive
https://www.php.net/manual/ja/function.array-merge-recursive.php
>array_merge_recursive (結合する配列...)
>戻り値：結合した配列

`array_merge_recursive`は配列を再帰的に結合します。
`array_merge_recursive`は連想配列の結合において意味があり、配列の場合は`array_merge`と同じ結果になります。

```php
php > $list1 = ['red', 'pink', 'blue'];
php > $list2 = ['green', 'yellow'];
php > $list3 = array_merge_recursive($list1, $list2);

// 数値のインデックスが順番に並んで結合される
php > var_export($list3);
array (
  0 => 'red',
  1 => 'pink',
  2 => 'blue',
  3 => 'green',
  4 => 'yellow',
)
```

### 連想配列
#### +演算子
```php
php > $list1 = ['key1' => 100];
php > $list2 = ['key2' => 200];
php > $list3 = $list1 + $list2;

php > var_export($list3);
array (
  'key1' => 100,
  'key2' => 200,
)
```
もしキーが重複する場合は配列の結合と同じく、基となる配列の値が残ります。

```php
php > $list1 = ['key1' => 100];
php > $list2 = ['key1' => 200];
php > $list3 = $list1 + $list2;

// 100がそのまま残る
php > var_export($list3);
array (
  'key1' => 100,
)
```

#### array_merge
https://www.php.net/manual/ja/function.array-merge.php
>array_merge (結合する配列...)
>戻り値：結合した配列

```php
php > $list1 = ['key1' => 100];
php > $list2 = ['key2' => 200];
php > $list3 = array_merge($list1, $list2);

php > var_export($list3);
array (
  'key1' => 100,
  'key2' => 200,
)
```
もしキーが重複する場合は+演算子と違い、結合する配列の値で上書きされます。

```php
php > $list1 = ['key1' => 100];
php > $list2 = ['key1' => 200];
php > $list3 = array_merge($list1, $list2);

// 200に上書きされる
php > var_export($list3);
array (
  'key1' => 200,
)
```

#### array_merge_recursive
https://www.php.net/manual/ja/function.array-merge-recursive.php
>array_merge_recursive (結合する配列...)
>戻り値：結合した配列

`array_merge_recursive`は配列を再帰的に結合します。
`array_merge`は文字列のキーが重複した場合に値を上書きしますが、`array_merge_recursive`は同じキーの値を一つにまとめます。

```php
php > $list1 = ['color1' => 'red', 'color2' => 'pink', 'color4' => 'blue'];
php > $list2 = ['color1' => 'green', 'color3' => 'yellow'];
php > $list3 = array_merge_recursive($list1, $list2);

// キー'color1'は$list1と$list2両方にあるので、値が一つにまとめられる
php > var_export($list3);
array (
  'color1' =>
  array (
    0 => 'red',
    1 => 'green',
  ),
  'color2' => 'pink',
  'color4' => 'blue',
  'color3' => 'yellow',
)
```

## 値の削除
配列から値を削除するには`unset`, `array_splice`, `array_shift`, `array_pop`, `array_diff`を使えます。

### unset
https://www.php.net/manual/ja/function.unset.php
>unset (配列, 削除する値のキー)
>戻り値：なし

キーを指定して値を削除します。

```php
php > $list1 = ['red', 'green', 'blue', 'black'];
php > unset($list1[1]); // greenを削除

php > var_export($list1);
array (
  0 => 'red',
  2 => 'blue',
  3 => 'black',
)
```
結果の**インデックスに注意**してください。
`unset`で削除した場合、インデックス番号は詰め直してくれないため、「1」番が空いている配列になります。
うっかり忘れてしまうとバグの原因になりますので、必ず`array_values`を使ってインデックスを詰めてあげましょう。
https://www.php.net/manual/ja/function.array-values.php
>array_values (配列)
>戻り値：配列

```php
php > var_export($list1);
array (
  0 => 'red',
  2 => 'blue', // 「1」番が空いている
  3 => 'black',
)
php > $list1 = array_values($list1);

php > var_export($list1);
array (
  0 => 'red',
  1 => 'blue',
  2 => 'black',
)
```
連想配列も同じくキーを指定することで値を削除できます。

また、キーを指定しないでリストをそのまま渡すと、リスト自体の削除ができます。
削除したリストは`NULL`になります。

```php
php > $list1 = ['red', 'green', 'blue', 'black'];
php > unset($list1);

php > var_dump($list1);
NULL
```

### array_splice
https://www.php.net/manual/ja/function.array-splice.php
>array_splice (配列, 開始位置, 削除する数)
>戻り値：削除した値の配列

範囲を指定して配列の一部を切り取ります。
第2引数で切り取り開始位置を指定、第3引数でいくつ切り取るかを指定します。

```php
php > $list1 = ['red', 'green', 'blue', 'black'];
php > array_splice($list1, 0, 2); // 最初から2つ切り取る

php > var_export($list1);
array (
  0 => 'blue',
  1 => 'black',
)
```
`unset`とは違い、インデックス番号は自動で詰められます。

第3引数を指定しない場合、開始位置より後ろの値を全て削除します。

```php
php > $list1 = ['red', 'green', 'blue', 'black'];
php > array_splice($list1, 1); // 1番目から全て削除する

php > var_export($list1);
array (
  0 => 'red',
)
```
### array_shift
https://www.php.net/manual/ja/function.array-shift.php
>array_shift (配列)
>戻り値：配列の最初の値

`array_shift`は配列の最初の値を切り取ります。

```php
php > $list1 = ['tokyo', 'osaka', 'nagoya'];
php > array_shift($list1);

php > var_export($list1);
array (
  0 => 'osaka',
  1 => 'nagoya',
)
```
インデックス番号は自動で詰められます。

### array_pop
https://www.php.net/manual/ja/function.array-pop.php
>array_pop (配列)
>戻り値：配列の最後の値

`array_pop`は配列の最後の値を切り取ります。

```php
php > $list1 = ['tokyo', 'osaka', 'nagoya'];
php > array_pop($list1);

php > var_export($list1);
array (
  0 => 'tokyo',
  1 => 'osaka',
)
```
### array_diff
https://www.php.net/manual/ja/function.array-diff.php
>array_diff (配列, 比較する配列)
>戻り値：比較した結果の配列

`array_diff`は配列同士を比較して差分を取るメソッドです。
第1引数に指定した配列の値の中で、比較対象の配列には**存在しない**値を返します。
特定の値のみを全て削除したい場合に使えます。

```php
php > $list1 = ['tokyo', 'osaka', 'nagoya', 'kyoto', 'osaka'];
php > $list1 = array_diff($list1, ['osaka']); // 削除する値を配列で渡す

php > var_export($list1);
array (
  0 => 'tokyo',
  2 => 'nagoya',
  3 => 'kyoto',
)
```
`unset`と同じく`array_values`でインデックス番号の詰め直しが必要です。

`array_diff`はメソッド名から「差分を取る」と解釈されるため、そのまま使うと「差分を取りたい」のか、「値を削除したい」のか意図がパッと見てわかりづらいです。
削除として使いたい場合は、意図が分かりやすい名前でラップして使うと良いです。

```php
function remove_values($list, $target) {
    return array_diff($list, [$target]);
}

$list1 = ['apple', 'banana', null, 'orange'];
// メソッドの中身に関係なく「削除」の意図が読み取れる
$list2 = remove_values($list1, null);

var_export($list2);
array (
  0 => 'apple',
  1 => 'banana',
  3 => 'orange',
)
```

## まとめ
ここまで配列の宣言から削除まで、基本的な使い方をまとめました。
思ったより長くなってしまったので、後は別記事にしました。
良かったら[【PHP 初級】配列おさらい➁ ～取得・検索・その他～](https://qiita.com/gksdyd88/items/a3c0f0af4e7b2afa6571)こちらもご一読ください。

### 参考にしたサイト
PHP公式サイト
[PHPで配列に要素を追加する方法](https://uxmilk.jp/8880)
[【PHP】連想配列、配列への追加](https://qiita.com/kazu56/items/6947a0e4830eb556d575)