Как сделать вложенный массив, разбив ключи по маске?

В PHP существует несколько способов создания вложенных массивов с разбиением ключей по маске. Рассмотрим два основных подхода.

Первый подход включает использование функций для работы с массивами, таких как array_combine(), array_walk_recursive() и explode(). Для начала необходимо создать исходный массив, содержащий все ключи в виде строки, разделенной маской. Например:

$data = [
    'person_name' => 'John Doe',
    'person_age' => 25,
    'company_name' => 'ACME Inc',
    'company_address' => '123 Main St',
    'company_city' => 'New York'
];

Затем можно разбить каждый ключ на отдельные части с помощью функции explode(), используя маску в качестве разделителя:

$newData = [];

foreach ($data as $key => $value) {
    $parts = explode('_', $key);
    $nestedArray = &$newData;

    foreach ($parts as $part) {
        if (!isset($nestedArray[$part])) {
            $nestedArray[$part] = [];
        }

        $nestedArray = &$nestedArray[$part];
    }

    $nestedArray = $value;
}

В результате получается вложенный массив $newData:

$newData = [
    'person' => [
        'name' => 'John Doe',
        'age' => 25
    ],
    'company' => [
        'name' => 'ACME Inc',
        'address' => '123 Main St',
        'city' => 'New York'
    ]
];

Второй подход включает использование рекурсии для разбиения ключей. Этот подход полезен, если ваши данные содержат неизвестное количество уровней вложенности. Начнем с создания функции array_mask():

function array_mask(array $data, string $mask) {
    $result = [];

    foreach ($data as $key => $value) {
        if (preg_match('/^' . $mask . '/', $key)) {
            $parts = explode('_', $key);
            $subKey = array_shift($parts);
  
            if (!isset($result[$subKey])) {
                $result[$subKey] = [];
            }
  
            $result[$subKey] = array_mask([$key => $value], implode('_', $parts));
        }
    }

    return $result;
}

Теперь можно вызвать функцию array_mask() и передать ей исходные данные и маску ключей:

$newData = array_mask($data, 'person');

Результатом будет вложенный массив $newData:

$newData = [
    'person' => [
        'name' => 'John Doe',
        'age' => 25
    ]
];

Оба подхода решают задачу создания вложенных массивов с разбиением ключей по маске, и выбор между ними зависит от конкретных требований и предпочтений в вашем проекте.