将类别列表转换为多维数组

时间:2018-08-08 22:25:11

标签: php php-7

我有一个预算类别列表,其中子类别用冒号分隔,如下所示:

<?php
$categories = [
    'Budget:Necessities' => 0,
    'Budget:Necessities:Phone' => 200.00,
    'Budget:Necessities:Home' => 0,
    'Budget:Necessities:Home:Rent' => 450.00,
    'Budget:Savings' => 500,
    'Budget:Savings:Vacation' => 300,
];

我希望它变成这样的东西:

<?php
$categories = [
    'Necessities' => [
        'balance' => 0,
        'Phone' => [
            'balance' => 200.00,
        ],
        'Home' => [
            'balance' => 0,
            'Rent' => [
                'balance' => 450,
            ],
        ],
    ],
    'Savings' => [
        'balance' => 500.00,
        'Vacation' => [
            'balance' => 300.00,
        ],
    ],
];

我很难弄清楚如何将一个变成另一个。

我认为最好使用递归函数,但它使我难以理解。

1 个答案:

答案 0 :(得分:1)

记下fubar发布的链接,其中https://github.com/illuminate/support/blob/master/Arr.php#L514包含一个“设置”功能,该功能将根据字符串输入在不同深度动态设置数组元素。

例如如果您有一个名为$foo的空数组,并且调用了set($foo, "level1.level2", "someValue");,则$foo随后将看起来如下(从对print_r()的调用):

Array
(
    [level1] => Array
        (
            [level2] => someValue
        )

)

通过毫不掩饰地整合了非常有用的功能,该解决方案实际上非常简单:

<?php
$categories = [
    'Budget:Necessities' => 0,
    'Budget:Necessities:Phone' => 200.00,
    'Budget:Necessities:Home' => 0,
    'Budget:Necessities:Home:Rent' => 450.00,
    'Budget:Savings' => 500,
    'Budget:Savings:Vacation' => 300,
];

$output = array();
//loop each array entry. $key will be the string, $val will be the balance
foreach ($categories as $key => $val)
{
  $levels = str_replace(":", ".", $key); //replace : with . for compatibility with the set() function
  $levels = substr(strstr($levels, '.'), 1); //remove the "Budget" entry
  set($output, "$levels.balance", $val); //set a "balance" entry for each item
}

print_r($output); //output using print_r for demonstration, but you can output some other way, as per your needs.

function set(&$array, $key, $value)
    {
        if (is_null($key)) {
            return $array = $value;
        }
        $keys = explode('.', $key);
        while (count($keys) > 1) {
            $key = array_shift($keys);
            // If the key doesn't exist at this depth, we will just create an empty array
            // to hold the next value, allowing us to create the arrays to hold final
            // values at the correct depth. Then we'll keep digging into the array.
            if (! isset($array[$key]) || ! is_array($array[$key])) {
                $array[$key] = [];
            }
            $array = &$array[$key];
        }
        $array[array_shift($keys)] = $value;
        return $array;
    }
?>

将为您提供以下输出:

Array
(
    [Necessities] => Array
        (
            [balance] => 0
            [Phone] => Array
                (
                    [balance] => 200
                )
            [Home] => Array
                (
                    [balance] => 0
                    [Rent] => Array
                        (
                            [balance] => 450
                        )
                )
        )
    [Savings] => Array
        (
            [balance] => 500
            [Vacation] => Array
                (
                    [balance] => 300
                )
        )
)

此处的工作演示:https://eval.in/1045835