PHP5上級試験/準上級試験の上級合格に挑戦(8)　5章配列中編

# ５章配列
+ ５章配列で要注意なところは、前編でもやった配列のイレギュラーな作り方、覚えなくてはならない配列に関する多数の関数、並べ替え処理。
+ 配列に関わる多数の関数は、多いだけではなく、複雑な処理をするハードな関数もある
+ 今回はその配列に関わる多数の関数についてほぼ全部ドリル形式で

## 要素作成・要素数取得

（１） 連続する整数、または文字列を値とする配列を作成する関数は？
（２）　配列の要素数を数える関数が２つあるがそれは？
（３）　配列に値を継ぎ足す関数は？　
（４）　（１）を使って　１〜５，a~eと、それぞれ連続する整数と文字列を持つ配列$a,$bを作成するコードを記述せよ
（５）　（４）を（２）を使って数えて正常に処理がされるか確かめよ（１つめの関数は数字配列に、２つめは文字列配列に）
（６）　（４）で作った＄aに「-」を継ぎ足して全体で要素数が１０個になるようにせよ
　
　
　
　
以下解答
　
　
(1) range()
(2) count() , sizeof()
(3) array_pad()

```index.php
//(4)
$a = range(1,5);
$b = range('a','e');
//(5)
print count($a);
print "<br>";
print sizeof($b);
print "<br>";
//(6)
$c = array_pad($a,10,"-");
print_r($c);
```

出力結果
5
5
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => - [6] => - [7] => - [8] => - [9] => - )

※range(int/string \$min int/string \$max)
※count/sizeofは引数に配列１つのみ
※array_pad(array \$target,int \$array_size,mixed \$pad_value) １番目が継ぎ足す先、２番めが完成時の要素数、３番めが継ぎ足すもの。
※<b>length()というような関数はPHPにはない</b>ので要注意。JSをかじった人がひっかかりやすい問題
※ちなみに１０といっても要素カウントは０からはじまるので要素としては９までになる。

##配列の展開と抽出

（１）配列の値をそれぞれの変数に入れる関数は？
（２）配列から要素を抽出し別の配列に入れる関数は？
（３）配列を指定した要素数のかたまりに分割する関数は？
（４）配列の不要な要素を削除し、指定があれば要素の挿入もできる関数は？
（５）（１）をつかって\$a = array(2012,2,28)から、＄ｙ，＄ｍ，＄ｄにそれぞれの値を入れて○年○月○日と出力せよ
（６）（１）をつかって\$b = array(2021,12,25)から、\$m,\$dにそれぞれの値を入れて○月○日と出力せよ
(7) \$c = range('a','e'); とし、２番めから２つぶん取り出し、\$otherに入れ、「１つめ、２つめ」というふうに間に「、」を入れて出力せよ
（８） \$d = range('a','f'); とし、３番目以降を削除して＄dを出力せよ
（９） \$e = range('a','f'); とし、３番目以降から２つ分を削除して\$eを出力せよ
(１０)　\$f = range('a','f'); とし、３番目以降から２つ分を削除してその後に4番目から\$g = array('x','y')を挿入して$fを出力せよ。

(11) \$h = range('a','e');とし、２つに分割したものを$iに入れて出力せよ
 　
　
　
　
　
解答
（１）list() (2) array_slice() (3) array_chunk() (4) array_splice()　

```index.php
//(5)
$a = array(2012,2,28);
list($y,$m,$d) = $a;
echo $y,'年';
echo $m,'月';
echo $d,'日';
print '<br>';

//(6)
$b = array(2021,12,25);
list(,$m,$d) = $b;
echo $m,'月';
echo $d,'日';
print '<br>';

//(7)
$c = range('a','e');
$other =array_slice($c,1,2);
echo $other[0],'.',$other[1];
print '<br>';

//(8)
$d = range('a','f');
array_splice($d,2);
print_r($d);
print '<br>';

//(9)
$e = range('a','f');
array_splice($e,2,2);
print_r($e);
print '<br>';

//(10)
$f = range('a','f');
$g = array('x','y');
array_splice($f,2,2,$g);
print_r($f);
print '<br>';

//(11)
$i = range('a','e');
$j = array_chunk($i,2);
print_r($j);

```

出力結果
2012年2月28日
12月25日
b.c
Array ( [0] => a [1] => b )
Array ( [0] => a [1] => b [2] => e [3] => f )
Array ( [0] => a [1] => b [2] => x [3] => y [4] => e [5] => f )
Array ( [0] => Array ( [0] => a [1] => b ) [1] => Array ( [0] => c [1] => d ) [2] => Array ( [0] => e ) )

※array_sliceとarray_spliceは綴りが似ており、間違いやすいので注意。
(ちなみにsliceは薄切り、spliceは切り取って接合させるという意味合いがある）
※（５）は左に関数がある。確かに[@tmak_tsukamotoさん記事](https://qiita.com/tmak_tsukamoto/items/2eb6d10e83b6c00981c9)の言う通り、違和感ありあり。なぜ右に入れる形式にしなかったのか。
※list()は、配列の要素数　< 関数の引数（変数）　の場合、余った変数にはNULLが入る
※list()は、配列の要素数　> 関数の引数（変数）　の場合、余った要素については無視される
※list()は、（６）のように記述を省略することもできる
※array_slice()は要素数が０から数えることから、関数の引数から＋１した位置からになることに注意。
※逆に次の引数は＋１しないことにも注意。
※array_splice()も、array_sliceと注意事項は同じ。
※array_chunk（）は、余った分はそのまま次の配列の要素の塊となる。

## キーや値の操作

（１）配列のキーだけを集めた配列を作る関数は？
（２）配列に特定のキーが有るかどうかを調べる関数は？２つ
（３）（２）の２つの違いは？
（４）値が配列にあるかどうかを調べる関数は？
（５）値を指定してそれに対応するキーを検索する関数は？
（６） \$search_array = array('1st' => null, '2nd' => 4,'3rd' => 'css');を作成し、
　　(２）の方法で出力せよ
（７）（６）で作成した配列から、キーだけを集めた配列\$array_keys_onlyを作成、出力せよ
（８）　'CSS'という値が存在するか調べ、あれば、それに対応するキーを出力せよ
　
　
　
解答
（１）array_keys(array $array)

（２）isset(mixed var):bool 引数は配列名[キー名]、array_key_exists(mixed $key,array $search_target):bool

（３）issetは引数が配列名[キー名]であるからか、キーに対応する値がNULLならfalseを返す。
　したがって、<b>値がNULLであってもなくてもキーが存在するかどうかを調べるにはarray_key_existsを使う</b>

（４）in_array(mixed $value, array $target)：bool
　　見つかったらTrue/そうでないならFalse

（５）array_search(mixed $value,array $target) :boo/mixed
  見つかったら値に対応するキーを返し、そうでないならfalseを返す

```index.php
$search_array = array('1st' => null, '2nd' => 4,'3rd' => 'css');
//(6)
If (isset($search_array['1st'])){
  echo 'True';
} else {
  echo 'False';
};
print '<br>';
If (array_key_exists('1st', $search_array)){
  echo 'True';
} else {
  echo 'False';
};
print '<br>';
//(7)
$array_keys_only = array_keys($search_array);
print_r($array_keys_only);
print '<br>';
//(8)
If (in_array('css',$search_array)){
  echo array_search('css',$search_array);
}
```
出力結果

False
True
Array ( [0] => 1st [1] => 2nd [2] => 3rd )
3rd

※isset()はもともと変数がセット（宣言）されてるかどうかを調べるもので、配列に対しても適用できるが挙動が異なる。ちなみに<b>nullというのは空白("")を意味するものではない</b>。つまり空白の場合はTrueが返る。　（[参考:isset|PHPマニュアル](https://www.php.net/manual/ja/function.isset.php)）
※echoだとTrue/Falseは返ってこないので、IFとEchoを使って出力
※<b>array_searchで、値が複数ある場合は、最初に見つかった要素のキーを返す。</b>

## 変数の展開
ここはルールを覚えるのみ。重要なのは２つ目か。１とか３はたぶんやっていたら当たり前な感じがする。

+ 配列が格納された変数でも、文字列内でもたとえば$a[0]などで変数の展開を行える。
+ ただし、多次元配列の場合は、配列全体を波括弧でくぐる。たとえば{$a[1][2]}とか。
+ 連想配列の場合は、{$a['PHP']}のように波括弧でくくった場合、'（シングルクォート）や”（ダブルクォート）でくくる

## 配列⇔変数の変換

（１）配列をそれぞれの変数に変換する関数は？
（２）それぞれの変数を配列に変換する関数は？
　
　
　
解答
（１）extract(array \$array[,int \$extract_type=EXTRA_OVERWRITE[,string \$prefix =NULL]])
（２）compact(mixed \$var1[,mixed $var2...]]);
（3） $size = "Large";
    $var_array = array("color" => "Skyblue",
                   "size"  => "Medium",
                   "shape" => "Sphere");

   var_arrayをそれぞれの変数に変換せよ。衝突する場合は「Medium」を頭にいれること。

（４）　変数color,size,shape,extra_sizeを配列$location_varsに変換して出力せよ。

（５）　変数\$phase="round", \$face_type="beard"の２つの変数名を\$addの配列に入れ、
　　　変数color,size,そして$addをあわせて＄vars_listに変換して出力せよ。


```index.php
<?php

$size = "Large";
$var_array = array("color" => "Skyblue",
                   "size"  => "Medium",
                   "shape" => "Sphere");
extract($var_array, EXTR_PREFIX_SAME, "extra");

echo "$color, $size, $shape, $extra_size";
print "<br>";

$location_vars = compact("color","size","shape","extra_size");

print_r($location_vars);
print "<br>";
$phase = "round";
$face_type = "beard";

$add = array("phase","face_type");

$vars_list = compact("color","size",$add);

print_r($vars_list);

?>

```

出力結果
Skyblue, Large, Sphere, Medium
Array ( [color] => Skyblue [size] => Large [shape] => Sphere [extra_size] => Medium )


※exractは連想配列でないと使えない。
※extract_typeは出力の型。
EXTRA_OVERWRITE（衝突があったら上書きする(デフォルト））
EXTRA_SKIP（衝突があったら上書きしない）
EXTR_PREFIX_SAME（衝突があった場合、＄prefixを頭につける）
EXTR_PREFIX_ALL（衝突のあるなしに関係なく\$prefixを頭につける）
EXTR_PREFIX_INVALID（無効な値やデータのキーに$prefixをつける
他にもあるが、現時点ではこれぐらいでよいかと思う。（[参考｜PHPマニュアル](https://www.php.net/manual/ja/function.extract.php))
※extractは、PREFIXを使う場合最初に「_(アンダーバー）」がつく。
※そもそもcompactに変数名を入れるのではなく、文字列として変数名を入れる。(下記）　紛らわしいので注意
× compact(\$color,\$size) →　○ compact("color","size")
※compactは$var○に配列も入れることができる。その場合、配列の中のそれぞれの値の文字列が変数名として使われる

## 配列の順次処理とイテレータ

+ 配列の各要素にアクセスするにはforeach文がうってつけ
+ イテレータ（iterator）とは反復子ともよばれ、配列やそれに類似するものの各要素に対する繰り返し処理のこと
+ VBAではイテレータがないのでクラスで作るしかない。カウント変数のiみたいなもの？かな？　ちょっと違うような気もする

ともかく問題

（１）　イテレータが指し示すキー名を出力する関数は？
（２）　イテレータが指し示すキーの値を出力する関数は？
（３）　イテレータが指し示すキーと値を配列にして返し、イテレータを次へ進める関数は？
（４）　イテレータを前の要素へ戻す関数は？
（５）　イテレータを次の要素へすすめる関数は？
（６）　イテレータを配列末尾にすすめ、その値を返す関数は？
（７）　イテレータを一番前に戻し、その値を返す関数は？
（８）　$a = array('No' => 'Name',
            1    => 'Tanaka',
            2    => 'Sekuchi',
            3    => 'Uchida',
            4    => 'Minakami');
　　次の配列で、イテレータを一番前に戻し、そのキーと値を出力する。
　　イテレータを次に移動させ、そこから、No:1,Tanaka...を次々と出力させるコードを書け。

　
　
　
　
　
解答
（１） key() (2) current() (3) each() (4) prev() (5) next() (6)end() (7) reset()
(8)は以下

```index.php
$a = array('No' => 'Name',
            1    => 'Tanaka',
            2    => 'Sekuchi',
            3    => 'Uchida',
            4    => 'Minakami');

reset($a);
$no = key($a);
echo $no;
print '<br>';
$name = current($a);
echo $name;
print '<br>';
next($a);
while(list($v1,$v2)= each($a)){
  echo  "$no.$v1,$name:$v2";
  print '<br>';
}

```

出力結果

No
Name
No.1,Name:Tanaka
No.2,Name:Sekuchi
No.3,Name:Uchida
No.4,Name:Minakami

（６）と（７）は値を返すが、返り値が必要ない場合は変数に入れなければOK。
たとえば　\$a = reset($b)でなく、reset（＄ｂ）でよいってこと。