流行りに乗ってみた。
結論
もうちょっと仕様が明確にならないと厳しい。
ぶっちゃけparserの方が重要だよねこれ。
お題
PHPで動的n次元配列追加をしたいです。例えば以下のように明示的に['a']['b']... - Yahoo!知恵袋
実装
再利用が出来るのでそれなりに画期的ではなかろうか。
<?php
echo str_repeat('=', 36), PHP_EOL;
echo "お題:a((b((c)))) => ['a' => [['b'=>[['c']]]]]", PHP_EOL;
echo str_repeat('=', 36), PHP_EOL;
echo "['a' => [['b'=>[['c']]]]]を実際展開するとこうなる。", PHP_EOL;
var_dump(['a' => [['b'=>[['c']]]]]);
echo PHP_EOL;
//超☆手抜きparser
$string = 'a((b((c))))';
$keys = explode('(', str_replace(')', '', $string));
$keys = array_map(function ($value) {return $value === '' ? 0 : $value;}, $keys);
$value = array_pop($keys);
$keys[] = 0;
//一括DONE
$result = set_lowest([], $keys, $value);
echo PHP_EOL;
echo "ウチの実行結果。", PHP_EOL;
var_dump($result);
echo PHP_EOL;
/**
* 指定された階層にある値を設定します。
*
* @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;
}
実行結果
====================================
お題:a((b((c)))) => ['a' => [['b'=>[['c']]]]]
====================================
['a' => [['b'=>[['c']]]]]を実際展開するとこうなる。
array(1) {
["a"]=>
array(1) {
[0]=>
array(1) {
["b"]=>
array(1) {
[0]=>
array(1) {
[0]=>
string(1) "c"
}
}
}
}
}
ウチの実行結果。
array(1) {
["a"]=>
array(1) {
[0]=>
array(1) {
["b"]=>
array(1) {
[0]=>
array(1) {
[0]=>
string(1) "c"
}
}
}
}
}
手前味噌
大分前にこんなクラスを作っていたわけで。
関数の元ネタのArrays::SetLowest()は商用環境での実績もあるのでまぁ使用は許されるのではなかろうか。
Arrays.php
<?php
/** ______ _ _ _ ___
* | ____| | | | | |__ \
* | |__ | |_ ___ __| |__ ___ ___| | ) |
* | __| | | | | \ \ /\ / /| '_ \ / _ \/ _ \ | / /
* | | | | |_| |\ V V / | | | | __/ __/ |/ /_
* |_| |_|\__, | \_/\_/ |_| |_|\___|\___|_|____|
* __/ |
* |___/
*
* Flywheel2: the inertia php framework
*
* @category Flywheel2
* @package vartype
* @author wakaba <wakabadou@gmail.com>
* @copyright 2011- Wakabadou honpo (http://www.wakabadou.net/) / Project ICKX (http://www.ickx.jp/)
* @license http://opensource.org/licenses/MIT The MIT License MIT
* @varsion 2.0.0
*/
namespace ickx\fw2\vartype\arrays;
/**
* 配列ユーティリティです。
*
* @category Flywheel2
* @package vartype
* @author wakaba <wakabadou@gmail.com>
* @license http://opensource.org/licenses/MIT The MIT License MIT
* @varsion 2.0.0
*/
class Arrays {
/**
* 配列に値がある場合は値を、無い場合はデフォルト値を返します。
*
* @param mixed $array 値の取得元配列
* @param mixed $name キー名
* @param mixed $default_value デフォルト値
*/
public static function AdjustValue ($array, $name, $default_value = null) {
if (is_array($array) || $array instanceof \Traversable) {
foreach ((array) $name as $name) {
if (isset($array[$name])) {
return $array[$name];
}
}
}
return $default_value;
}
/**
* 渡された変数が配列の場合はそのまま配列として、配列以外の場合は配列にして返します。
*
* @param mixed $array 配列化したい変数
* @param unknown_type $call_back
* @return Ambigous <unknown, array, mixed>
*/
public static function AdjustArray ($array, $call_back = null) {
if ($call_back === null) {
return is_array($array) ? $array : (array) $array;
}
return (is_array($array)) ? $array : call_user_func($call_back, $array);
}
/**
* 変数がTraversableな値かどうか判定します。
*
* ※Traversableな値とはたとえばforeachで使えるものです。
*
* @param Traversable $array 判定する値
* @return bool Traversableな値の場合はbool TRUE、そうでない場合はbool FALSE
*/
public static function IsTraversable ($array) {
return is_array($array) || $array instanceof \Traversable;
}
/**
* 配列のうち、指定したキーの要素のみを結合して返します。
*
* @param string $glue 連結値
* @param array $array 対象の配列
* @param array $target_key_list 結合対象とするキーのリスト
* @return string 結合された値
*/
public static function SelectImplode ($glue, $array, $target_key_list) {
$tmp = [];
foreach ($target_key_list as $key) {
$tmp[] = $array[$key];
}
return implode($glue, $tmp);
}
/**
* 配列内の要素をbit値として合計します。
*
* @param array $bit_list 合計する配列
* @return float 合計された値
*/
public static function BitSum ($bit_list) {
if (!is_array($bit_list)) {
return $bit_list;
}
$bit_sum = 0;
foreach ($bit_list as $bit) {
$bit_sum |= $bit;
}
return $bit_sum;
}
/**
* 配列の中にキーが存在するか検証します。
*
* @param array $array 検索対象の配列
* @param mixed $key 検索するキー
* @return bool 対象のキーが存在する場合はtrue、そうでない場合はfalse
*/
public static function KeyExists ($array, $key) {
return isset($array[$key]) || array_key_exists($key, $array);
}
/**
* 指定した階層の配列にキーが存在するか検証します。
*
* @param array $array 検索対象の配列
* @param mixed $key 検索するキー
* @return bool 対象のキーが存在する場合はtrue、そうでない場合はfalse
*/
public static function ExistsLowest ($array, $keys) {
foreach ((array) $keys as $key) {
if (isset($array[$key])) {
$array = $array[$key];
} else {
return false;
}
}
return true;
}
/**
* 指定された階層にある値でソートします。
*
* @param array $array ソートする配列
* @param mixed $name 階層
* @return array ソートされた配列
*/
public static function SortLowest ($array, $name) {
uasort(
$array,
function ($current, $next) use ($name) {
return strnatcmp(static::GetLowest($current, $name), static::GetLowest($next, $name));
}
);
return $array;
}
/**
* 指定された階層にある値で逆順ソートします。
*
* @param array $array ソートする配列
* @param mixed $name 階層
* @return array ソートされた配列
*/
public static function ReverseSortLowest ($array, $name) {
uasort(
$array,
function ($current, $next) use ($name) {
return -1 * strnatcmp(static::GetLowest($current, $name), static::GetLowest($next, $name));
}
);
return $array;
}
/**
* 指定された階層にある値を削除します。
*
* @param array $array 削除する値を持つ配列
* @param mixed $keys 階層
* @return array 値を削除された配列
*/
public static function RemoveLowest ($array, $keys) {
$keys = (array) $keys;
$target_key = array_pop($keys);
$tmp =& $array;
foreach ($keys as $key) {
$tmp =& $tmp[$key];
}
unset($tmp[$target_key]);
return $array;
}
/**
* 指定された階層にある値を取得します。
*
* @param array $array 配列
* @param mixed $keys 階層
* @return mixed 指定された改造にある値
*/
public static function GetLowest ($array, $keys) {
foreach ((array) $keys as $key) {
if (isset($array[$key])) {
$array = $array[$key];
} else {
return null;
}
}
return $array;
}
/**
* 指定された階層にある値を設定します。
*
* @param array $array 配列
* @param mixed $keys 階層
* @return array 設定後の配列
*/
public static function SetLowest ($array, $keys, $value) {
$keys = (array) $keys;
if (empty($array)) {
$tmp =& $array;
} else {
$tmp =& $array[array_shift($keys)];
}
foreach ($keys as $key) {
if ($tmp instanceof \ickx\fw2\vartype\arrays\LazyArrayObject) {
if ($tmp->$key === null) {
$tmp->$key = null;
}
$tmp =& $tmp->$key;
} else {
if (!isset($tmp[$key])) {
$tmp[$key] = null;
}
$tmp =& $tmp[$key];
}
}
$tmp = $value;
return $array;
}
/**
* 配列にあるキーの値を元に配列を階層化して返します。
*
* @param array $values 階層化する配列
* @param array $keys 階層化の元にするキー名の配列
* @param callable $filter 最終階層を詰める際に利用するコールバック
* @return array 階層化された配列
*/
public static function DimensionalTransformation ($values, $keys = [], $filter = null) {
if (is_array($keys) && empty($keys) || $keys === null) {
return $values;
}
$keys = (array) $keys;
$ret = [];
foreach ($values as $row) {
$tmp =& $ret;
foreach ($keys as $key) {
$tmp =& $tmp[$row[$key]];
}
if ($filter !== null && is_callable($filter)) {
$row = $filter($row);
}
$tmp = $row;
}
return $ret;
}
/**
* 配列から指定したキーに紐付く値のみを抽出し返します。
*
* 値が存在しない場合は値がnullとなります。
*
* @param array $array
* @param array $keys
*/
public static function GetElementsByKeys (array $array, array $keys) {
return array_filter(array_combine($keys, array_map(function ($key) use ($array) {
return isset($array[$key]) ? $array[$key] : null;
}, $keys)));
}
/**
* 再帰的に空要素を削除して配列を縮小します。
*
* @param array $array 空要素を削除する配列
* @param callable $call_back 独自の空判定処理
* @return 空要素を削除された配列
*/
public static function RecursiveFilter ($array, $call_back = null) {
if (!is_callable($call_back)) {
foreach ($array as $idx => $element) {
if (is_array($element)) {
$array[$idx] = static::RecursiveFilter($element, $call_back);
if (empty($array[$idx])) {
unset($array[$idx]);
}
}
if ($element === null) {
unset($array[$idx]);
}
}
} else {
foreach ($array as $idx => $element) {
if (is_array($element)) {
$array[$idx] = static::RecursiveFilter($element, $call_back);
if (empty($array[$idx])) {
unset($array[$idx]);
}
}
if ($call_back($element, $idx)) {
unset($array[$idx]);
}
}
}
return $array;
}
/**
* キーを維持したまま配列をシャッフルします。
*
* @param array $array シャッフルする配列
* @return array シャッフルされた配列
*/
public static function Shuffle ($array) {
$result = [];
foreach(array_keys($array) as $key){
$result[$key] = $array[$key];
}
return $result;
}
}
PHP5.4が出た当初に作り直したモノなので、array_columnは使っていません。
悪しからず。