Рекурсивное объединение массивов PHP с цифровыми клавишами


Итак, я предполагаю динамически создавать многомерный массив из текстового файла, и все работает отлично, за исключением того, что цифровые клавиши меня обманывают...

Текстовый файл выглядит примерно так:

a=1
b.c=2
b.d.0.e=3
b.d.0.f=4
b.d.1.e=5
b.d.1.f=6

Поскольку array_merge_recursive не работает с цифровыми клавишами, вывод выглядит следующим образом:

array(2) { 
 ["a"]=>  
 string(3) "1" 
 ["b"]=>  
 array(2) { 
  ["c"]=>  
  string(3) "2" 
  ["d"]=>  
  array(4) { 
   [0]=>  
   array(1) { 
    ["e"]=>  
    string(9) "3" 
   } 
   [1]=>  
   array(1) { 
    ["f"]=>  
    string(4) "4" 
   } 
   [2]=>  array(1) { 
    ["e"]=>  
    string(8) "5" 
   } 
   [3]=>  
   array(1) { 
    ["f"]=>  
    string(9) "6" 
 }}}}

Есть ли какое-нибудь простое решение, чтобы сделать вывод таким, как...?

array(2) { 
 ["a"]=>  
 string(3) "1" 
 ["b"]=>  
 array(2) {
  ["c"]=>  
  string(3) "2" 
  ["d"]=>  
  array(2) { 
   [0]=>  
   array(2) { 
    ["e"]=>  
    string(9) "3" 
    ["f"]=>  
    string(4) "4"  
   } 
   [1]=>  
   array(3) { 
    ["e"]=>  
    string(9) "5"
    ["f"]=>  
    string(4) "6"
}}}}

Спасибо

Author: per_pilot, 2010-01-12

3 answers

Вы можете разбить каждый бит на его компоненты и создавать массив по одному шагу за раз.

$path = "b.d.0.e";
$val = 3;
$output = array();

$parts = explode(".", $path);

// store a pointer to where we currently are in the array.
$curr =& $output;

// loop through up to the second last $part
for ($i = 0, $l = count($parts); $i < $l - 1; ++$i) {
    $part = $parts[$i];

    // convert numeric strings into integers
    if (is_numeric($part)) {
        $part = (int) $part;
    }

    // if we haven't visited here before, make an array
    if (!isset($curr[$part])) {
        $curr[$part] = array();
    }

    // jump to the next step
    $curr =& $curr[$part];
}

// finally set the value
$curr[$parts[$l - 1]] = $val;

Мой вывод, используя тот же ввод, что и ваш:

Array (
    [a] => 1
    [b] => Array (
        [c] => 2
        [d] => Array (
            [0] => Array (
                [e] => 3
                [f] => 4
            )
            [1] => Array (
                [g] => 5
                [h] => 6
            )
        )
    )
)
 3
Author: nickf, 2010-01-12 13:57:42

Или вы могли бы использовать оценку():

$raw_data = file($txt_file, FILE_IGNORE_NEW_LINES);
foreach ($raw_data as $line) {
    list($keys, $value) = explode('=', $line);
    $keys = explode('.', $keys);
    $arr_str = '$result';
    foreach ($keys as $key) {
        if (ctype_digit($key)) {
            $arr_str .= "[" . $key . "]";
        } else {
            $arr_str .= "['" . $key . "']";
        }
    }
    eval($arr_str . ' = $value;');
}

print_r($result);
 0
Author: GZipp, 2010-01-12 14:35:45

Я знаю, что это старое, но лучшее решение, которое я нашел, - использовать array_replace_recursive. Это позволит достичь того, что вы хотите сделать:

$start = array(
   "600" => array("total" => 100),
   "700" => array("total" => 200)
);

$finish = array(
  "600" => array("average" => 25),
  "700" => array("average" => 50)
);

$out = array_replace_recursive($start,$finish);
var_dump($out):

array(2) {
  [600]=>
  array(2) {
    ["total"]=>
    int(100)
    ["average"]=>
    int(25)
  }
  [700]=>
  array(2) {
    ["total"]=>
    int(200)
    ["average"]=>
    int(50)
  }
}
 0
Author: John B, 2014-11-20 21:47:24