45歳から始めるプログラミング PHP編 No1 多次元配列を1次元配列に変換する関数を書け！(再帰処理で)

![study-php 2018-04-29 22-40-55.png](https://qiita-image-store.s3.amazonaws.com/0/5354/f90fadad-02bf-cca1-7741-a25b835b6979.png)

こんにちは。nouphetです。

私はインフラエンジニアなのでbash以外のコードはほぼ書いてなかったのですが、最近プログラムを書きたくなってPHPの勉強をはじめました。

最初は[Udemy](https://www.udemy.com/jp/)で基礎知識を学んでいたのですが、同僚の @reoring や @suin が課題を出してくれて挑戦したので、経過の記録として公開します。

ちなみにUdemyはオンラインで学ぶことができるサービスで普段は1コース数千円〜数万円するのですが、たまにキャンペーンをやっていて千円台で購入することができるタイミングがあるので、そこを狙うと割りとお金を掛けずに学べるし早いので良いです。

ちなみに私はこの2コースを学びました。
* [PHP初級プログラミング講座　初級　その１| Udemy](https://www.udemy.com/php-gtoa/learn/v4/overview) ←キャンペーン価格で 1,700円でした。
* [PHP初級プログラミング講座　初級 その2 | Udemy](https://www.udemy.com/php-2-kh/learn/v4/overview)  ←キャンペーン価格で 1,500円でした。

そして同僚が出してくれた課題がこちら。

## 多次元配列を1次元配列に変換する関数を書け！(再帰処理で)

```php
<?php

$a = [1, [2, [3, [4, [5]]]]];
$b = [1, 2, 3, 4, 5];

function f($a) {
	// ここを実装してね
}

$c = f($a);

if ($b === $c) {
	echo "OK";
} else {
	echo "NG";
}
```

この課題を解決することで
* 配列の扱い方
* 再帰関数の書き方
を学ぶが出来ます。

## 実装してみた第1弾

実装はいろいろな方法で出来るようですが、お題として「再帰処理で」という条件が含まれていたのでそれなりに調べ悩みながら実装してみました。

```n_array2.php
<?php

$a = [1, [2, [3, [4, [5]]]]];
$b = [1, 2, 3, 4, 5];
// 値が数値だとわかりずらかったので検証中は英文字に置き換え
// $a = ['a', ['b', ['c', ['d', ['e']]]]];
// $b = ['a', 'b', 'c', 'd', 'e'];
// $a = [1, "aaa"=>"AAA", [2, [3, [4, [5]]]]];
// $b = [1, "AAA", 2, 3, 4, 5];

function f($a) {
	// ここを実装してね
	global $c;
	foreach ($a as $key => $value) {

		if (is_array($value)) {
			$a = $a[$key];
			f($a);
		} else {
			$c[] = $value;
		}
	}
	// echo 'var_dump($c)' . "\n";
	// var_dump($c);
	// echo "\n";
	return $c;
	unset($c);
}

$c = f($a);

if ($b === $c) {
	echo "OK\n";
} else {
	echo "NG\n";
}
```

再帰関数ということで関数の中で同じ関数を呼び出すということはわかった。しかしforeachの中から再帰的に処理した結果を取り出すということがうまくできなかったので、globalを使って実装してみた。処理結果としてはOKだったが、なんとなくglobalは使うと大きなプログラムの中で使う時にまずいんじゃないかなーとは思っていると、やはりその通りで｢今度はglobal使わずにやってみて｣とコメントをもらったので、再び挑戦。

## 実装してみた第2弾

ファイル番号が6になっていますが、試行錯誤の結果増えていきましたw
コードがごちゃごちゃしてきて混乱してきたらすっきり新しく書き始めるのが良さそうです :grinning:

```n_array6.php
<?php

$a = [1, [2, [3, [4, [5]]]]];
$b = [1, 2, 3, 4, 5];
// $a = ['a', ['b', ['c', ['d', ['e']]]]];
// $b = ['a', 'b', 'c', 'd', 'e'];
// $a = ['a', ['b']];
// $b = ['a', 'b'];
// $a = [1, "aaa"=>"AAA", [2, [3, [4, [5]]]]];
// $b = [1, "AAA", 2, 3, 4, 5];
// $a = [a, ["AAA"], [b, [c, [d, [e]]]]];
// $b = [a, "AAA", b, c, d, e];

// print_r($b);

function f($a) {
	// ここを実装してね
	$ret = array();
	foreach ($a as $key => $value) {
		if(! is_array($value)) {
			// echo 'if value = ';
			// var_dump($value);

			$ret[] = $value;

			// echo 'ret = ';
			// var_dump($ret);
		} else {
			// $a = $value;

			// echo 'else value = ';
			// var_dump($value);
			$ret = array_merge($ret, f($value));
		}
	}
	// echo '===3=== $ret = ';
	// var_dump($ret);
	return $ret;
}

$c = f($a);

// echo '============================' . "\n";
// echo 'var_dump($c)_3' . "\n";
// echo join(',',$c);
// echo "\n";

if ($b === $c) {
	echo "OK\n";
} else {
	echo "NG\n";
}
```

### 実行結果
```
$ php n_array6.php
OK
```

なんとか処理を実装することができた。
次に再帰関数を使ってフィボナッチ数列を出力する関数を書くというお題をもらったので、次の記事に書きたいと思う。

ちなみにこのシリーズの進捗は [YYPHP](https://yyphp.connpass.com/event/) でもお題の共有や進捗報告をしています。

また、「わかばちゃんと学ぶシリーズ」著者の @llminatoll や他の方ももチャレンジしているので、他の人はどう実装しているのか興味のある方はぜひ覗いてみてください〜！ 

* @llminatoll [PHP Quiz - llminatoll](https://scrapbox.io/llminatoll/PHP_Quiz)
* [#YYPHP で出されたクイズの回答 | yumemi-kuwahara
](https://gist.github.com/yumemi-kuwahara/3d5891229dbecf3e7354c474bfb0b3db)
* [TAKAHASHI Kunihikoさんのツイート: "ひねくれものなので、再帰じゃないパターン。 https://t.co/o4LI4FVaze… "](https://twitter.com/kunit/status/986991117571784705)

興味のある方はぜひチャレンジしてみてください！！

## 出題者からの回答例はこちら

これからチャレンジしようと思っている人は見ないで〜！

* [PHPクイズの解答例 - HackMD](https://hackmd.io/yIF4h2A7QcGXnxSNN79Fkg)

## YYPHPは毎週やってます

PHPについてワイワイ話したい方は、[YYPHPのイベント情報](https://yyphp.connpass.com/)をチェックしてみて下さい。

最近、Slackや [[YYPHP - YouTubeライブ]](https://www.youtube.com/watch?v=awAxGz4KFLo&t=4s)での参加者も多くなってきたので次回募集分からオンライン参加枠も作りました！当日現地に来れない方もオンラインでぜひご参加ください！

ではでは、また！:smiley: