dopod0901 2015-12-08 02:08
浏览 12
已采纳

PHP平面数组嵌套['a','b','c']到['a'=> ['b'=>'c']] - 高级[关闭]

I need an improved version of this task:

PHP flat array to nested ["a", "b", "c"] to ["a" =>["b"=>["c"]]]

I want to convert:

[
    ['2015', '01', 'Sydney', 12],
    ['2015', '01', 'London', 34],
    ['2015', '02', 'Sydney', 56],
]

to the following: eg if level == 2:

$data[2015]['01'] = ['London', 34]; 
// note 2015, 01, Syney, 12 is overwritten by later record as they have same array keys
$data[2015]['02'] = ['Sydney', 56];

if level === 3:

$data[2015]['01']['Sydney'] = 12; 
//only one element auto convert to value instead of array
$data[2015]['01']['London'] = 34;
$data[2015]['02']['Sydney'] = 56;

And here is a working version: which need improve

<?php
$rows = array(
    array('year' => 2015, 'month' => '01', 'city' => 'Sydney', 'qty' => 12),
    array('year' => 2015, 'month' => '01', 'city' => 'London', 'qty' => 34),
    array('year' => 2015, 'month' => '02', 'city' => 'Sydney', 'qty' => 56),
);
echo '<pre>';
echo 'original data =';
print_r($rows);

echo "
 level=2 and result =
";
$data = arr($rows);
print_r($data);

echo "
 level=3 and result =
";
$data = arr($rows, 3);
print_r($data);

function arr($rows = array(), $level = 2) {
    foreach ($rows[0] as $k => $v) $col[] = $k;
    $num = count($col);
    if ($num < 1) return;//err no data
    if ($num ==1) return; //donot worry this i will figure out later
    if ($level > $num) $level = $num;
    $arr = array();
    foreach ($rows as $row) {
        $k=$col[0]; $ref=&$arr[$row[$k]]; unset($row[$k]);
        if ($level>1){
            $k=$col[1]; $ref=&$ref[$row[$k]]; unset($row[$k]);
            if ($level>2){
                $k=$col[2]; $ref=&$ref[$row[$k]]; unset($row[$k]);
                if ($level>3){
                    $k=$col[3]; $ref=&$ref[$row[$k]]; unset($row[$k]);
                    if ($level>4){
                        $k=$col[4]; $ref=&$ref[$row[$k]]; unset($row[$k]);
                        if ($level>5){//too geek! max 6 level
                            $k=$col[5]; $ref=&$ref[$row[$k]]; unset($row[$k]);
                            $ref=(count($row)<2 ? current($row) : $row);
                        }else $ref=(count($row)<2 ? current($row) : $row);
                    }else $ref=(count($row)<2 ? current($row) : $row);
                }else $ref=(count($row)<2 ? current($row) : $row);
            }else $ref=(count($row)<2 ? current($row) : $row);
        }else $ref=(count($row)<2 ? current($row) : $row);
    }
    return $arr;
}

And I have a new solution:

<?php
$arr = [
    ['y'=>2014, 'm'=>10, 'd'=>10, 'q'=>20141010, 't'=>1],
    ['y'=>2014, 'm'=>10, 'd'=>15, 'q'=>20141015, 't'=>2],
    ['y'=>2014, 'm'=>12, 'd'=>11, 'q'=>20141211, 't'=>3],
    ['y'=>2014, 'm'=>12, 'd'=>22, 'q'=>20141222, 't'=>4],
    ['y'=>2015, 'm'=>10, 'd'=>12, 'q'=>20151012, 't'=>5],
    ['y'=>2015, 'm'=>12, 'd'=>25, 'q'=>20151225, 't'=>6],
];
echo '<pre>origin=';
print_r($arr);
echo 'level=0';
print_r(arr($arr));
echo 'level=1';
print_r(arr($arr, 1));
echo 'level=2';
print_r(arr($arr, 2));
echo 'level=3';
print_r(arr($arr, 3));
echo 'level=4';
print_r(arr($arr, 4));
echo 'level=5';
print_r(arr($arr, 5));

function arr($arr = [], $level = 0) {
    $num = count($arr[0]);
    if (!$num) return []; //no data
    if ($level >= $num) $level = $num - 1;

    if ($level < 1) {
        if ($num === 1) {
            foreach ($arr as $r) {
                $data[] = reset($r);
            }
            return $data;
        }
        return $arr;
    }

    $keys = array_keys($arr[0]);
    $keys = array_slice($keys, 0, $level);
    echo "
keys=";
    print_r($keys);
    foreach ($arr as $i => $r) {
        $ref = &$data[$r[$keys[0]]];
        foreach ($keys as $j => $k) {
            if ($j) {
                $key = $r[$k];
                $ref = &$ref[$key];
            }
            unset($r[$k]);
        }
        $ref = count($r) > 1 ? $r : reset($r);
    }
    return $data;
}

and here is the new result:

origin=Array
(
[0] => Array
    (
        [y] => 2014
        [m] => 10
        [d] => 10
        [q] => 20141010
        [t] => 1
    )

[1] => Array
    (
        [y] => 2014
        [m] => 10
        [d] => 15
        [q] => 20141015
        [t] => 2
    )

[2] => Array
    (
        [y] => 2014
        [m] => 12
        [d] => 11
        [q] => 20141211
        [t] => 3
    )

[3] => Array
    (
        [y] => 2014
        [m] => 12
        [d] => 22
        [q] => 20141222
        [t] => 4
    )

[4] => Array
    (
        [y] => 2015
        [m] => 10
        [d] => 12
        [q] => 20151012
        [t] => 5
    )

[5] => Array
    (
        [y] => 2015
        [m] => 12
        [d] => 25
        [q] => 20151225
        [t] => 6
    )

)
level=0Array
(
[0] => Array
    (
        [y] => 2014
        [m] => 10
        [d] => 10
        [q] => 20141010
        [t] => 1
    )

[1] => Array
    (
        [y] => 2014
        [m] => 10
        [d] => 15
        [q] => 20141015
        [t] => 2
    )

[2] => Array
    (
        [y] => 2014
        [m] => 12
        [d] => 11
        [q] => 20141211
        [t] => 3
    )

[3] => Array
    (
        [y] => 2014
        [m] => 12
        [d] => 22
        [q] => 20141222
        [t] => 4
    )

[4] => Array
    (
        [y] => 2015
        [m] => 10
        [d] => 12
        [q] => 20151012
        [t] => 5
    )

[5] => Array
    (
        [y] => 2015
        [m] => 12
        [d] => 25
        [q] => 20151225
        [t] => 6
    )

)
level=1
keys=Array
(
[0] => y
)
Array
(
[2014] => Array
    (
        [m] => 12
        [d] => 22
        [q] => 20141222
        [t] => 4
    )

[2015] => Array
    (
        [m] => 12
        [d] => 25
        [q] => 20151225
        [t] => 6
    )

)
level=2
keys=Array
(
[0] => y
[1] => m
)
Array
(
[2014] => Array
    (
        [10] => Array
            (
                [d] => 15
                [q] => 20141015
                [t] => 2
            )

        [12] => Array
            (
                [d] => 22
                [q] => 20141222
                [t] => 4
            )

    )

[2015] => Array
    (
        [10] => Array
            (
                [d] => 12
                [q] => 20151012
                [t] => 5
            )

        [12] => Array
            (
                [d] => 25
                [q] => 20151225
                [t] => 6
            )

    )

)
level=3
keys=Array
(
[0] => y
[1] => m
[2] => d
)
Array
(
[2014] => Array
    (
        [10] => Array
            (
                [10] => Array
                    (
                        [q] => 20141010
                        [t] => 1
                    )

                [15] => Array
                    (
                        [q] => 20141015
                        [t] => 2
                    )

            )

        [12] => Array
            (
                [11] => Array
                    (
                        [q] => 20141211
                        [t] => 3
                    )

                [22] => Array
                    (
                        [q] => 20141222
                        [t] => 4
                    )

            )

    )

[2015] => Array
    (
        [10] => Array
            (
                [12] => Array
                    (
                        [q] => 20151012
                        [t] => 5
                    )

            )

        [12] => Array
            (
                [25] => Array
                    (
                        [q] => 20151225
                        [t] => 6
                    )

            )

    )

)
level=4
keys=Array
(
[0] => y
[1] => m
[2] => d
[3] => q
)
Array
(
[2014] => Array
    (
        [10] => Array
            (
                [10] => Array
                    (
                        [20141010] => 1
                    )

                [15] => Array
                    (
                        [20141015] => 2
                    )

            )

        [12] => Array
            (
                [11] => Array
                    (
                        [20141211] => 3
                    )

                [22] => Array
                    (
                        [20141222] => 4
                    )

            )

    )

[2015] => Array
    (
        [10] => Array
            (
                [12] => Array
                    (
                        [20151012] => 5
                    )

            )

        [12] => Array
            (
                [25] => Array
                    (
                        [20151225] => 6
                    )

            )

    )

)
level=5 same as level=4 
  • 写回答

2条回答 默认 最新

  • douyu0725 2015-12-08 03:04
    关注

    (1) Updated to support multiple arrays at once

    (2) Updated to merge all child arrays into one array

    You can do this by using deneds answer and specifying a level that gets decremented on every recursion. I'm using deneds solution as an anonymous recursive function inside a foreach loop:

    function nested(array $array, $level = 1)
    {
        for ($i = 0; $i < count($array); ++$i) {
            $nest = function(array $a, $l = 1) use (&$nest) {
                return count($a) < 2
                    ? $a[0]
                    : ($l == 0 ? $a : [array_shift($a) => $nest($a, --$l)]);
            };
    
            $array[$i] = count($array[$i]) == 0 ? [] : $nest(array_values($array[$i]), $level);
        }
    
        return array_replace_recursive(...$array); // Splat-Operator available in PHP >= 5.6
        // array_merge_recursive() does not work on numerical keys
    }
    
    $data = array(
        array('year' => 2015, 'month' => '01', 'city' => 'Sydney', 'qty' => 12),
        array('year' => 2015, 'month' => '01', 'city' => 'London', 'qty' => 34),
        array('year' => 2015, 'month' => '02', 'city' => 'Sydney', 'qty' => 56),
    );
    
    var_dump( nested($data, 2) );
    

    This will output:

    enter image description here

    If there's only one array left, the value of the only array element will be applied:

    var_dump( nested($data, 3) );
    

    Will result in:

    enter image description here

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 在不同的执行界面调用同一个页面
  • ¥20 基于51单片机的数字频率计
  • ¥50 M3T长焦相机如何标定以及正射影像拼接问题
  • ¥15 keepalived的虚拟VIP地址 ping -s 发包测试,只能通过1472字节以下的数据包(相关搜索:静态路由)
  • ¥20 关于#stm32#的问题:STM32串口发送问题,偶校验(even),发送5A 41 FB 20.烧录程序后发现串口助手读到的是5A 41 7B A0
  • ¥15 C++map释放不掉
  • ¥15 Mabatis查询数据
  • ¥15 想知道lingo目标函数中求和公式上标是变量情况如何求解
  • ¥15 关于E22-400T22S的LORA模块的通信问题
  • ¥15 求用二阶有源低通滤波将3khz方波转为正弦波的电路