3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPで動的n次元配列追加をしたいです。 例えば複数の階層を持つ配列です。

Last updated at Posted at 2016-02-12

流行りライド
PHPで動的n次元配列追加をしたいです。 例え… - Qiitaをもうちょっと真面目に対応したもの

仕様

  • 最下層以外は全てキーとみなす
  • "("の前に任意の文字が無い場合は、配列の追加とみなす

実装


echo str_repeat('=', 36), PHP_EOL;
echo "お題:a((b((c))d((e)))) => ['a' => [['b'=>[['c']], 'd' => [['e']]]]]", PHP_EOL;
echo str_repeat('=', 36), PHP_EOL;
echo "['a' => [['b'=>[['c']], 'd' => [['e']]]]]を実際展開するとこうなる。", PHP_EOL;
var_dump(['a' => [['b'=>[['c']], 'd' => [['e']]]]]);
echo PHP_EOL;

$target = 'a((b((c))d((e))))';

//比較的真面目parser
$stacker = parser($target);

//一括DONE
$result = [];
foreach ($stacker as $stack) {
	$value = array_pop($stack);
	$result = set_lowest($result, $stack, $value);
}

echo PHP_EOL;
echo "ウチの実行結果。", PHP_EOL;
var_dump($result);
echo PHP_EOL;

echo str_repeat('=', 36), PHP_EOL;
echo "拡張お題:a((((c))((e)))) => ['a' => [[[['c']], [['e']]]]]", PHP_EOL;
echo str_repeat('=', 36), PHP_EOL;
echo "['a' => [[[['c']], [['e']]]]]を実際展開するとこうなる。", PHP_EOL;
var_dump(['a' => [[[['c']], [['e']]]]]);
echo PHP_EOL;

$target = 'a((((c))((e))))';

//比較的真面目parser
$stacker = parser($target);

//一括DONE
$result = [];
foreach ($stacker as $stack) {
	$value = array_pop($stack);
	$result = set_lowest($result, $stack, $value);
}

echo PHP_EOL;
echo "ウチの実行結果。", PHP_EOL;
var_dump($result);
echo PHP_EOL;

/**
 * 指定された文字列を解析し、チャンクとして返します。
 *
 * @param	string	$target	解析対象の文字列
 * @return	array	解析済みのチャンク 階層ツリーごとに1配列を持つ配列
 */
function parser ($target) {
	$key_buffer = [];
	$value_buffer = [];
	$stacker = [];

	for ($i = 0, $max = mb_strlen($target, ENCODING);$i < $max;$i++) {
		$char = mb_substr($target, $i, 1, ENCODING);
		switch ($char) {
			case '(' :
				$key_buffer[] = empty($value_buffer) ? count(get_lowest($stacker, array_keys($key_buffer))) : implode('', $value_buffer);
				$value_buffer = [];
				break;
			case ')':
				if (!empty($value_buffer)) {
					$key_buffer[] = 0;
					$key_buffer[] = implode('', $value_buffer);
					$stacker[] = $key_buffer;
				}
				array_pop($key_buffer);
				array_pop($key_buffer);
				$value_buffer = [];
				break;
			default:
				$value_buffer[] = $char;
				break;
		}
	}

	return $stacker;
}

/**
 * 指定された階層にある値を設定します。
 *
 * @param	array	$array	配列
 * @param	mixed	$keys	階層
 * @return	array	設定後の配列
 */
function set_lowest ($array, $keys, $value) {
	$keys = (array) $keys;
	if (empty($array)) {
		$tmp =& $array;
	} else {
		$tmp =& $array[array_shift($keys)];
	}

	foreach ($keys as $key) {
		if (!isset($tmp[$key])) {
			$tmp[$key] = null;
		}
		$tmp =& $tmp[$key];
	}
	$tmp = $value;
	return $array;
}

/**
 * 指定された階層にある値を取得します。
 *
 * @param   array   $array  配列
 * @param   mixed   $keys   階層
 * @return  mixed   指定された改造にある値
 */
function get_lowest ($array, $keys) {
	foreach ((array) $keys as $key) {
		if (isset($array[$key])) {
			$array = $array[$key];
		} else {
			return null;
		}
	}
	return $array;
}

実行結果

====================================
お題:a((b((c))d((e)))) => ['a' => [['b'=>[['c']], 'd' => [['e']]]]]
====================================
['a' => [['b'=>[['c']], 'd' => [['e']]]]]を実際展開するとこうなる。
array(1) {
  ["a"]=>
  array(1) {
    [0]=>
    array(2) {
      ["b"]=>
      array(1) {
        [0]=>
        array(1) {
          [0]=>
          string(1) "c"
        }
      }
      ["d"]=>
      array(1) {
        [0]=>
        array(1) {
          [0]=>
          string(1) "e"
        }
      }
    }
  }
}


ウチの実行結果。
array(1) {
  ["a"]=>
  array(1) {
    [0]=>
    array(2) {
      ["b"]=>
      array(1) {
        [0]=>
        array(1) {
          [0]=>
          string(1) "c"
        }
      }
      ["d"]=>
      array(1) {
        [0]=>
        array(1) {
          [0]=>
          string(1) "e"
        }
      }
    }
  }
}

====================================
拡張お題:a((((c))((e)))) => ['a' => [[[['c']], [['e']]]]]
====================================
['a' => [[[['c']], [['e']]]]]を実際展開するとこうなる。
array(1) {
  ["a"]=>
  array(1) {
    [0]=>
    array(2) {
      [0]=>
      array(1) {
        [0]=>
        array(1) {
          [0]=>
          string(1) "c"
        }
      }
      [1]=>
      array(1) {
        [0]=>
        array(1) {
          [0]=>
          string(1) "e"
        }
      }
    }
  }
}


ウチの実行結果。
array(1) {
  ["a"]=>
  array(1) {
    [0]=>
    array(2) {
      [0]=>
      array(1) {
        [0]=>
        array(1) {
          [0]=>
          string(1) "c"
        }
      }
      [1]=>
      array(1) {
        [0]=>
        array(1) {
          [0]=>
          string(1) "e"
        }
      }
    }
  }
}
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?