将字符串分成assoc数组

时间:2017-02-19 20:19:47

标签: php arrays

我有一个这样的字符串:

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

我需要将它转换为这样的数组:

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

我使用爆炸来分割碎片,但我不知道接下来需要做什么。

$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?
    }
}

3 个答案:

答案 0 :(得分: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];
        }
    }
}

希望这有帮助!

答案 1 :(得分: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"
                        )
                )
        )
)

答案 2 :(得分: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);