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