2010-01-12 5 views
2

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

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

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" 
}}}} 

Благодаря

+0

Любое из решений в ответах будет работать, но я хотел бы предложить, кому хранит данные, как это, что это будет сделано более правильно (например, с помощью json). – GZipp

ответ

3

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

$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 
      ) 
     ) 
    ) 
) 
+0

Спасибо за хороший ответ :) Если if (is_numeric) не нужен, я думаю, что он уже интерпретирует var как int. –

0

Или вы могли бы использовать eval():

$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

Я знаю, что это старый, но самое лучшее решение, которое я найти - использовать 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) 
    } 
}