Форматировать простой массив в многомерном

У меня есть простой массив в PHP:

Array
(
    [max_size_video] => 50000
    [max_size_photo] => 8000
    [token_expire] => 100
    [dns] => mydns.fr
    ...
)

Я хотел бы преобразовать этот массив в многомерный формат с подчеркиванием в качестве разделителя:

Array
(
    [max] => Array
        (
            [size] => Array
                (
                     => 50000
                    [photo] => 8000
                )
        )
    [token] => Array
        (
            [expire] => 100
        )
    [dns] => mydns.fr
    ...
)

Я могу сделать это с помощью следующего уродливого кода:

$item = explode('_', $row);
switch (count($item)) {
  case 1:
    $array[$item[0]] = $value;
  break;
  case 2:
    $array[$item[0]][$item[1]] = $value;
  break;
  case 3:
    $array[$item[0]][$item[1]][$item[2]] = $value;
  break;
  case 3:
    $array[$item[0]][$item[1]][$item[2]][$item[3]] = $value;
  break;
  ...
}

Как я могу сделать это с помощью более элегантной функции?

2 ответа
2

Ссылочная переменная избавит вас от этого ужасного раздувания кода!

Вы можете выполнять итеративные вызовы этот ответ на переполнение стека с 2012 года.

Код: (Демо)

function assignArrayByPath(&$arr, $path, $value, $separator="_") {
    $keys = explode($separator, $path);
    foreach ($keys as $key) {
        $arr = &$arr[$key];
    }
    $arr = $value;
}
    
foreach ($array as $key => $value) {
    unset($array[$key]);
    assignArrayByPath($array, $key, $value);
}
var_export($array);

Или свести это к следующему: (Демо)

function assignArrayByPath(&$result, $path, $value) {
    foreach (explode('_', $path) as $key) {
        $result = &$result[$key];
    }
    $result = $value;
}

$result = [];
foreach ($array as $key => $value) {
    assignArrayByPath($result, $key, $value);
}
var_export($result);

Этот метод потребует, чтобы вы построили логические (не мучительные) пути в качестве ключей. Я имею в виду:

  1. Если после 'max_size_photo' => 8000вы заявляете 'max' => 10000, то вы получите сообщение об ошибке.
  2. Если после 'max_size_photo' => 8000вы заявляете 'max_size' => 10000, то вы удалите ранее развернутые (более глубокие) элементы из выходного массива.

  • Большое спасибо вам. Это для получения данных в базе данных и отправки json в моем интерфейсе

    — Локомасс

  • Если у вас есть возможность изменить значения базы данных, было бы лучше преобразовать эти данные в JSON. перед сохранение в базе данных. Тогда вам нужно только позвонить в стандартную json_decode() когда тянешь за рядок. Современные версии MySQL также предлагают манипуляции с JSON (но они могут не понадобиться для вашего использования).

    — микмакуса

Мик уже дал хорошее решение почасового вопроса.

Принимая во внимание, что это могло быть просто для иллюстрации, я заметил switch оператор имеет избыточный регистр:


 case 3:
    $array[$item[0]][$item[1]][$item[2]] = $value;
  break;
  case 3:
    $array[$item[0]][$item[1]][$item[2]][$item[3]] = $value;
  break;

Здесь второй case 3 недоступен — возможно, это была опечатка и должна была быть case 4. Это не приведет к ошибке, а приведет к появлению лишних строк кода, которые могут ввести в заблуждение любого, кто читает код, включая вас в будущем!

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *