[PHP] 文字列処理などの備忘録集

## 背景
プログラミングテストの勉強でphpを使って問題解いているのですが、使えるやり方をストックしておかないと中々向上しないなと思ったので、Qiitaをお借りしてメモ代わりにコードを置いておきます。
自分用メモなので分かりにくかったらすみません。誰かの役に立てばいいなくらいで公開しておきます。

## 文字列処理
### 正規表現の勉強になるサイト
[手を動かしながら覚える正規表現＜基礎入門編＞](http://doc.mas3.net/regexp/#character)
[サルにも分かる正規表現入門](http://www.mnet.ne.jp/~nakama/)
[正規表現チェッカー](http://okumocchi.jp/php/re.php)

### ある文字列が含まれるかどうか
```php
// 文字列を配列へ変換
$letters = str_split($sentence);

// 小文字のアルファベットをすべて「含まなければ」true
if (array_diff(range('a', 'z'), $letters)) {
    // 処理
}
```

### HTMLタグの中身を抜き出し
参考：[phpのpreg_matchで特定の文字列のあとの何かを抜き出す](https://qiita.com/ritukiii/items/13155c9300c5802c7abf)

```php
$tag1 = "<a>";
$tag2 = "<\/a>"; // \つけないと/が区切り文字認識されてしまう

$search = "dummy <a>answer1 </a>dummydummy <a>answer2</a>";

// ?をつけると最初にマッチした文字列を抜き出す
// ()をつけるとその部分にマッチした文字列を$matchesの中にいれる
preg_match("/$tag1(.*?)$tag2/", $search, $matches);
// $matchesの中身
/*
array(2) {
  [0]=>
  string(15) "<a>answer1 </a>"
  [1]=>
  string(8) "answer1 "
}
*/

// 一致するもの全てを抜き出す場合は preg_match_all() を使う
preg_match_all("/$tag1(.*?)$tag2/", $search, $matches);
// $matchesの中身
/*
array(2) {
  [0]=>
  array(2) {
    [0]=>
    string(15) "<a>answer1 </a>"
    [1]=>
    string(14) "<a>answer2</a>"
  }
  [1]=>
  array(2) {
    [0]=>
    string(8) "answer1 "
    [1]=>
    string(7) "answer2"
  }
}
*/
```
### 文字列⇔配列
```php
/*** 文字列 → 配列 ***/
// 1文字ごとに区切って配列にしたい場合
$s_array = str_split($s);
// 区切り文字を指定する場合
$pizza  = "piece1 piece2 piece3 piece4 piece5 piece6";
$pieces = explode(" ", $pizza);
echo $pieces[0]; // piece1
echo $pieces[1]; // piece2

/*** 配列 → 文字列 ***/
$s = implode($s_array);
// 空文字以外で結合したい場合
// implode($s_array, ",");
```

### 文字列のカウント（正規表現使用）
```php
// 文字列中の大文字の数をカウント
// どういう文字をカウントするかは正規表現で指定
// 引数の3つ目は各パターンによる 置換を行う最大回数。デフォルトは -1 (制限無し)
preg_replace("/[A-Z]/","",$s,-1,$count);
```

### 文字列の置換とカウント
```php
// 2 となります
// ll->"" 置換
$str = str_replace("ll", "", "good golly miss molly!", $count);
echo $count;
```

[PHP公式：substr_count](http://php.net/manual/ja/function.substr-count.php)

```php
// 重なっている副文字列はカウントされないので、1 が表示される
$text2 = 'gcdgcdgcd';
echo substr_count($text2, 'gcdgcd');
```

### ある文字列が順番通りに出現するかどうか
```php
// 正規表現
if(preg_match('/.*a.*b.*c.*/',$s)){
    // 出現した場合の処理
}
```

### 連続する文字が文字列中に存在するかどうか
```php
// 任意の一文字の連続が存在するかどうかで判定
preg_match('/(.)\1/',$string)
```

### 重複する文字を消す
```php
// array_valuesをしないと配列のインデックスが不連続になる
$s_array = array_values(array_unique($s));
```

### ASCⅡ値関連
https://ja.wikipedia.org/wiki/ASCII

```php
// 文字→ASCⅡ値
ord($s);
// ASCⅡ値→文字
chr($s);
```

### 小文字/大文字に変換
```php
// 小文字に変換
strtolower($s);
// 大文字に変換
strtoupper($s);
```

### 文字の判定
```php
// すべて大文字かどうか判定
ctype_upper($s);
// すべて小文字かどうか判定
ctype_lower($s);
// すべて英文字かどうか判定
ctype_alpha($s);
```

### 部分文字列
[PHP公式：substr](http://php.net/manual/ja/function.substr.php)

```php
echo substr('abcdef', 1);     // bcdef
echo substr('abcdef', 1, 3);  // bcd
echo substr('abcdef', 0, 4);  // abcd
echo substr('abcdef', 0, 8);  // abcdef
echo substr('abcdef', -1, 1); // f

// 文字列中の 1 文字にアクセスすることも
// "角括弧" を使用することで可能
$string = 'abcdef';
echo $string[0];                 // a
echo $string[3];                 // d
echo $string[-1];                // f
```
### 文字列を逆順にする
```php
echo strrev("Hello world!"); // 出力は "!dlrow olleH" となります
```

## 配列
### 配列の生成
```php
// array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
$array = range(0, 12); 
// array(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
range(0, 100, 10);
```
### 配列の中に値があるかどうか
```php
$os = array("Mac", "NT", "Irix", "Linux");
if (in_array("Irix", $os)) {
    echo "Got Irix";
}
```
### 配列の結合
```php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
/*
Array
(
    // 連想配列で同一キーの場合はarray2の値で上書き
    [color] => green
    [0] => 2
    [1] => 4
    [2] => a
    [3] => b
    [shape] => trapezoid
    [4] => 4
)
*/
```
### 配列の部分配列の取得
[PHP公式：array_slice](http://php.net/manual/ja/function.array-slice.php)

```php
$input = array("a", "b", "c", "d", "e");

$output = array_slice($input, 2);      // "c", "d", "e" を返す
$output = array_slice($input, -2, 1);  // "d" を返す
$output = array_slice($input, 0, 3);   // "a", "b", "c" を返す
```

### 配列の共通項を抜き出す
[PHP公式：array_intersect](http://php.net/manual/ja/function.array-intersect.php)

```php
$array1 = array("a" => "green", "red", "blue");
$array2 = array("b" => "green", "yellow", "red");
$result = array_intersect($array1, $array2);
/*
Array
(
    [a] => green
    [0] => red
)
*/
```
### 配列から先頭のn個の要素のみを配列で取得
``` php
$arr = array(10, 20, 30, 40, 50);
$n = 3;
array_slice($arr, 0, $n);
// 結果
// array (
//   0 => 10,
//   1 => 20,
//   2 => 30,
// )
```

### 配列の要素の削除（キーごと）
[PHPで配列から特定の要素を削除する](https://qiita.com/Quantum/items/767dba44af81d1825248)

```php
$target = array('a', 'b', 'c');

//削除実行
$split = array_splice($target, 1, 1);

//削除結果
var_dump($target);/*array(2) { [0]=> string(1) "a" [1]=> string(1) "c" }*/

//引数で渡した値も変更されている
var_dump($split);/*array(1) { [0]=> string(1) "b" }*/
```

## その他

### continue, breakのスキップレベル変更
```php
$i = 0;
while ($i++ < 5) {
    echo "Outer<br />\n";
    while (1) {
        echo "Middle<br />\n";
        while (1) {
            echo "Inner<br />\n";
            continue 3; // breakも同様
        }
        echo "This never gets output.<br />\n";
    }
    echo "Neither does this.<br />\n";
}
```

### クラス定義
```php
class v{
	// プロパティ
	public $pos_x;
	public $pos_y;

	// コンストラクタ(初期値の設定ver)
	function __construct($x = 0, $y = 0){
		$this->pos_x = $x;
		$this->pos_y = $y;
	}

	// メソッド
	public function echoPos(){
		echo "({$this->pos_x}, {$this->pos_y})\n";
	}
}

$v1 = new v();
$v1->pos_x = 1;
$v1->pos_y = 2;
$v1->echoPos();
/*(1, 2)*/

$v2 = new v(2,3);
$v2->echoPos();
/*(2, 3)*/
```