PHPで連想配列の任意の位置に要素を挿入・削除する

Qiita初投稿です。自分のブログに書いてたのを転載してみた。

PHPの配列関数には、配列の任意の位置に要素を挿入したり、任意の位置から要素を削除したりできるものがない。つとに連想配列に対して、substr的な感覚で要素の挿入・削除が出来たら幸せになれるのになぁ…と、とあるアプリケーションの開発をしていて、痛切にそう思った。
それなら、独自関数として作ってしまうのが手っ取り早い──で、早速作ってみた。
その名もずばり、`array_insert()`と`array_delete()`だ！
まぁ、思った以上に色んなケースで利用できるんではないかと。

#### 配列の任意の位置に要素を挿入

```php:array_insert()
/**
 * 配列（連想配列にも対応）の指定位置に要素（配列にも対応）を挿入して、挿入後の配列を返す
 * 
 * @param array &$base_array 挿入したい配列
 * @param mixed $insert_value 挿入する値（文字列、数値、配列のいずれか）
 * @param int $position 挿入位置（省略可能。先頭は0、省略時は配列末尾に挿入される）
 * @return boolean 挿入成功時にtrue
 **/
function array_insert(&$base_array, $insert_value, $position=null) {
	if (!is_array($base_array)) 
		return false;
	$position = is_null($position) ? count($base_array) : intval($position);
	$base_keys = array_keys($base_array);
	$base_values = array_values($base_array);
	if (is_array($insert_value)) {
		$insert_keys = array_keys($insert_value);
		$insert_values = array_values($insert_value);
	} else {
		$insert_keys = array(0);
		$insert_values = array($insert_value);
	}
	$insert_keys_after = array_splice($base_keys, $position);
	$insert_values_after = array_splice($base_values, $position);
	foreach ($insert_keys as $insert_keys_value) {
		array_push($base_keys, $insert_keys_value);
	}
	foreach ($insert_values as $insert_values_value) {
		array_push($base_values, $insert_values_value);
	}
	$base_keys = array_merge($base_keys, $insert_keys_after);
	$is_key_numric = true;
	foreach ($base_keys as $key_value) {
		if (!is_integer($key_value)) {
			$is_key_numric = false;
			break;
		}
	}
	$base_values = array_merge($base_values, $insert_values_after);
	if ($is_key_numric) {
		$base_array = $base_values;
	} else {
		$base_array = array_combine($base_keys, $base_values);
	}
	return true;
}
```

#### 配列の任意の位置から指定数分の要素を削除

```php:array_delete()
/**
 * 配列（連想配列にも対応）の任意の位置から指定数分の要素を削除して、削除後の配列を返す
 * 
 * @param array &$base_array 要素を削除したい配列
 * @param int $delete_position 削除を開始する要素位置
 * @param int $delete_items 削除する要素数（省略可能。省略時は1つだけ削除）
 * @param boolean $reroll_index 削除後の配列の添字振り直しフラグ（省略可能。省略時はtrueで添字を振り直す。※数値添字のみの配列でない場合は振り直しは行わない）
 * @return boolean 削除成功時にtrue
 **/
function array_delete(&$base_array, $delete_position=null, $delete_items=1, $reroll_index=true) {
	if (!is_array($base_array)) 
		return false;
	if (is_null($delete_position) || !is_integer($delete_position)) 
		return false;
	if (!is_integer($delete_items) || intval($delete_items) == 0) 
		return false;
	$index_num = 0;
	foreach ($base_array as $key => $value) {
		if ($delete_position == $index_num) {
			unset($base_array[$key]);
			$delete_items--;
			$delete_position++;
		}
		if ($delete_items == 0) {
			break;
		}
		$index_num++;
	}
	$is_key_numric = true;
	foreach (array_keys($base_array) as $key_value) {
		if (!is_integer($key_value)) {
			$is_key_numric = false;
			break;
		}
	}
	if ($is_key_numric && $reroll_index) {
		$base_array = array_merge($base_array, array());
	}
	return true;
}
```

##### 使用例

```bash:
$base_array = ['A', 'B', 'C', 'D'];
$insert_data = 'Z';

// 配列（一次元）の指定位置に要素（値）を挿入する
array_insert($base_array, $insert_data, 3);
var_dump($base_array);

----
array(5) { 
  [0]=> string(1) "A"
  [1]=> string(1) "B"
  [2]=> string(1) "C"
  [3]=> string(1) "Z"
  [4]=> string(1) "D"
}
```

```bash:
$base_array = ['A'=>'a', 'B'=>'b', 'C'=>'c', 'D'=>'d'];
$insert_data = ['X'=>'x', 'Y'=>'y'];

// 連想配列の指定位置に要素（配列）を挿入する
array_insert($base_array, $insert_data, 3);
var_dump($base_array);

----
array(6) {
  ["A"]=> string(1) "a"
  ["B"]=> string(1) "b"
  ["C"]=> string(1) "c"
  ["X"]=> string(1) "x"
  ["Y"]=> string(1) "y"
  ["D"]=> string(1) "d"
}
```

```bash:
$base_array = ['A'=>'a', 'B'=>'b', 'C'=>'c', 'D'=>'d'];

// 連想配列の指定位置から指定数分の要素を削除する
array_delete($base_array, 1, 2);
var_dump($base_array);

----
array(2) {
  ["A"]=> string(1) "a"
  ["D"]=> string(1) "d"
}
```

```bash:
$base_array = ['A', 'B', 'C', 'D'];

// 配列（一次元）の指定位置から指定数分の要素を削除し、添字は振り直さない
array_delete($base_array, 2, 1, false);
var_dump($base_array);

----
array(3) {
  [0]=> string(1) "A"
  [1]=> string(1) "B"
  [3]=> string(1) "D"
}
```

個人的に、`array_delete()` が `substr()` ライクに使えるのが結構お気に入りだったり。