Разделить строку на ассоциированный массив

У меня есть такая строка:

$config = 'app.name = "My App";
app.id = "myappid";
app.components.cache.id = "Memcache";';

Мне нужно преобразовать его в массив, как это:

app=>[
'name=>'My App',
'id'=>'myappid',
'components'=>[
'cache'=>['id'=>'Memcache']
]
]

Я использую Explode для разделения на куски, но я не знаю, что мне нужно делать дальше.

$arr = explode(";", $config);
$data = [];
foreach ($arr as $item) {
$pieces = explode('=', $item);
$pieces_dotes = explode('.', $pieces[0]);
foreach ($pieces_dotes as $piece) {
//what i need to do here?
}
}

0

Решение

Как насчет этого? Внутри внутреннего foreach Цикл, вы назначаете временную переменную по ссылке на себя, поэтому вы создаете стек ключей массива, а затем присваиваете значение в конце.

$config = 'app.name = "My App";
app.id = "myappid";
app.components.cache.id = "Memcache";';
$arr = explode(";", $config);
$data = [];
foreach ($arr as $item) {
$temp = &$data;
$item = trim($item);
if (empty($item)) continue;
list($setting, $value) = explode("=", trim($item));
$setting = explode(".", trim($setting));
foreach ($setting as $set) {
$temp = &$temp[$set];
}
$temp = trim($value, '" ');
}
print_r($data);
0

Другие решения

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

<?php

$config = 'app.name = "My App";
app.id = "myappid";
app.components.cache.id = "Memcache";';

$arr = explode(";", $config);
$data = [];

foreach ($arr as $item) {
$pieces = explode('=', $item);
$currentValue = trim(str_replace('"', '', $pieces[1]));
$pieces_dotes = explode('.', $pieces[0]);

// Set initial value of $currentLevel to root of data array
$currentLevel = &$data;

// Initiate count & iterator vars
$numPieces = count($pieces_dotes);
$i = 0;
foreach ($pieces_dotes as $piece) {
// Increment $i and set $newKey to be trimmed version of current piece of the dot notated level
$i++;
$newKey = trim($piece);

// Skip empty $newKey
if(empty($newKey)) {
continue;
}

// Assign the $currentValue once we are at the required depth
if($i == $numPieces) {
$currentLevel[$newKey] = $currentValue;
}

// We are not at the required depth yet so initiate the key as an array if required
if(empty($currentLevel[$newKey])) {
$currentLevel[$newKey] = [];
}

// Set the $currentLevel to reference the new key
if(is_array($currentLevel[$newKey])) {
$currentLevel = &$currentLevel[$newKey];
}
}
}

Надеюсь это поможет!

0

Решение с использованием пользовательской рекурсивной функции fillBypath:

/**
* Fills an array by hierarchical 'key path'
*
* @param type $value value in each 'key path'
* @param type $keys hierarchical key list
* @param type $arr the resulting array(passed by reference)
*/
function fillByPath($value, $keys, &$arr) {
$c = count($keys) - 1;

foreach ($keys as $idx => $k) {
if ($idx == $c) {     // check if it's the last key in the "key path"$arr[$k] = $value;
break;
}

if (isset($arr[$k]) && is_array($arr[$k])) {
fillByPath($value, array_slice($keys, $idx + 1), $arr[$k]);
break;
} else {
$arr[$k] = [];
fillByPath($value, array_slice($keys, $idx + 1), $arr[$k]);
break;
}
}
}

$config = 'app.name = "My App";
app.id = "myappid";
app.components.cache.id = "Memcache";';

$result = [];
foreach (array_filter(explode(";", $config)) as $path) {
list($keyPath, $v) = explode(" = ", trim($path));
$keys = explode(".", $keyPath);  // getting key list
fillByPath($v, $keys, $result);
}

print_r($result);

Выход:

(
[app] => Array
(
[name] => "My App"[id] => "myappid"[components] => Array
(
[cache] => Array
(
[id] => "Memcache")
)
)
)
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector