Recursive function for building array from tree - php

I have an array that looks like this:
Array (
[0] => Array
(
[term_id] => 23
[name] => testasdf
[depth] => 1
)
[1] => Array
(
[term_id] => 26
[name] => asdf
[depth] => 2
)
[2] => Array
(
[term_id] => 31
[name] => Another level deep
[depth] => 3
)
[3] => Array
(
[term_id] => 32
[name] => Another level deep
[depth] => 2
)
[4] => Array
(
[term_id] => 24
[name] => testasdf
[depth] => 1
)
[5] => Array
(
[term_id] => 27
[name] => asdf
[depth] => 1
)
)
Here is the recursive function that I'm using, it works except in some cases (where the depth is greater it seems.
function process(&$arr, &$prev_sub = null, $cur_depth = 1) {
$cur_sub = array();
while($line = current($arr)){
if($line['depth'] < $cur_depth){
return $cur_sub;
}elseif($line['depth'] > $cur_depth){
$prev_sub = $this->process($arr, $cur_sub, $cur_depth + 1 );
}else{
$cur_sub[$line['term_id']] = array('term_id' => $line['term_id'], 'name' => $line['name']);
$prev_sub =& $cur_sub[$line['term_id']];
next($arr);
}
}
return $cur_sub;
}
This is how the results look:
Array
(
[23] => Array
(
[26] => Array
(
[31] => Array
(
[term_id] => 31
[name] => Another level deep
)
)
[32] => Array
(
[term_id] => 32
[name] => Another level deep
)
)
[24] => Array
(
[term_id] => 24
[name] => testasdf
)
[27] => Array
(
[term_id] => 27
[name] => asdf
)
)
Any idea how I can have it so the term_id and name is shown for all depths?

try this:
function process(&$arr, &$prev_sub = null, $cur_depth = 1) {
$cur_sub = array();
while($line = current($arr)){
if($line['depth'] < $cur_depth){
return $cur_sub;
}
if($line['depth'] > $cur_depth){
$prev_sub = $this->process($arr, $cur_sub, $cur_depth + 1 );
}
$cur_sub[$line['term_id']] = array('term_id' => $line['term_id'], 'name' => $line['name']);
$prev_sub =& $cur_sub[$line['term_id']];
next($arr);
}
return $cur_sub;
}

Related

Multidimensional array from matched values

I'm trying to get a multidimensional array comparing the [id] values with the [parent_id] values from an array like this:
Array
(
[0] => Array
(
[id] => 101
[title] => parent_101
[parent_id] => 0
[level] => 1
)
[1] => Array
(
[id] => 118
[title] => parent_118
[parent_id] => 0
[level] => 1
)
[2] => Array
(
[id] => 119
[title] => child_119
[parent_id] => 118
[level] => 2
)
[4] => Array
(
[id] => 173
[title] => subchild_173
[parent_id] => 119
[level] => 3
)
[5] => Array
(
[id] => 120
[title] => child_120
[parent_id] => 118
[level] => 2
)
[6] => Array
(
[id] => 145
[title] => deeperchild_145
[parent_id] => 173
[level] => 4
)
)
The result should be a new array like this:
Array
(
[0] => Array
(
[title] => parent_101
[id] => 101
[parent_id] => 1
[level] => 1
[childrens] => Array
(
)
)
[1] => Array
(
[id] => 118
[title] => parent_118
[parent_id] => 1
[level] => 1
[childrens] => Array
(
[0] => Array
(
[id] => 119
[title] => child_119
[parent_id] => 118
[level] => 2
[deeper] => Array
(
[0] => Array
(
[id] => 173
[title] => subchild_173
[parent_id] => 119
[level] => 3
[deeperchild] => Array
(
[id] => 145
[title] => deeperchild_145
[parent_id] => 173
[level] => 4
)
)
)
)
[1] => Array
(
[id] => 120
[title] => parent_120
[parent_id] => 118
[level] => 2
[deeper] => Array
(
)
)
)
)
)
so far I come up with this code but I'm stuck at the 3rd level deeper and I was wondering if there is a better way to do that.
> $parentsitms = array(); $deeperArr = array(); $childsArr = array();
> $childparent = array(); $menu = array();
>
> foreach ($list as $items) {
>
> if($items->level==='1'):
> $idparent = $items->id;
> $parents = $items->title;
> $parentsitms[] = ['id'=>$items->id,'title'=>$items->title,'parent_id'=>$items->parent_id,'level'=>$items->level];
>
> endif;
>
> }
> foreach ($parentsitms as $menuitm) {
> $parents = $menuitm;
>
> foreach($list as $chd){
>
> if($menuitm['id'] === $chd->parent_id):
> $childparent = $chd->id;
> $childsItms = ['id'=>$chd->id,'title'=>$chd->title,'parent_id'=>$chd->parent_id,'level'=>$chd->level];
> $childsArr[] = [array_merge($childsItms,array('deeper'=>array()))];
> endif;
>
> if($childparent === $chd->parent_id):
> $array = ['title'=>$chd->title,'id'=>$chd->id,'parent_id'=>$chd->parent_id,'level'=>$chd->level];
> $deeperArr[] = ['id'=>$chd->id,'title'=>$chd->title,'parent_id'=>$chd->parent_id,'level'=>$chd->level];
> $childsArr = [array_merge($childsItms,array('deeper'=>$deeperArr))];
> endif;
>
> ######## can't get the 4th level deeper ######
>
>
> }
>
> $menu[] = array_merge($parents,array('childrens'=>$childsArr));
> }
>
> echo '<pre>'; print_r($menu);
Any help is very appreciated.
This code uses a non-recursive method which is a more common method of solving this type of problem. I prefer this method as it makes just one pass through the data and can be easier to follow through (IMHO).
I've added comments to the code as it's easier to describe with the code. The only thing I would say is that this always uses children as the name of the child elements and not the way you do this at the moment...
// Order array so that they are in order of level
usort($list, function ( $a, $b ) { return $a['level'] <=> $b['level']; });
// Create start point with all of the items indexed by their ID
$output = array_column($list, null, "id");
// Work in reverse order
foreach ( array_reverse(array_column($list, "id")) as $id ) {
$parent = $output[$id]['parent_id'];
// If there is a parent to work with
if ( $parent != 0 ) {
// Ensure that the add point is there
if ( !isset($output[$parent]['children']) ) {
$output[$parent]['children'] = [];
}
// Prepend the new item to the list (do this as the items
// are added in reverse oder)
array_unshift($output[$parent]['children'], $output[$id]);
// Remove the old node from the base list
unset($output[$id]);
}
}
$output = array_values($output);
print_r($output);
gives...
Array
(
[0] => Array
(
[id] => 101
[title] => parent_101
[parent_id] => 0
[level] => 1
)
[1] => Array
(
[id] => 118
[title] => parent_118
[parent_id] => 0
[level] => 1
[children] => Array
(
[0] => Array
(
[id] => 119
[title] => child_119
[parent_id] => 118
[level] => 2
[children] => Array
(
[0] => Array
(
[id] => 173
[title] => subchild_173
[parent_id] => 119
[level] => 3
[children] => Array
(
[0] => Array
(
[id] => 145
[title] => deeperchild_145
[parent_id] => 173
[level] => 4
)
)
)
)
)
[1] => Array
(
[id] => 120
[title] => child_120
[parent_id] => 118
[level] => 2
)
)
)
)

PHP: Find elements in deep array, then modify each parent element

I have a varying level of deepness for a multidimensional array. I want to find the elements where UserId isset (see example array below), then add a key/value pair ([show] => true) to the matched element and each parent array. There may be multiple matches that will need to modify the parents.
I have this:
Array
(
[0] => Array
(
[id] => 3
[parent_id] => 0
[ownerEntityId] => 2
[children] => Array
(
[0] => Array
(
[id] => 15
[parent_id] => 3
[ownerEntityId] => 14
[children] => Array
(
[0] => Array
(
[id] => 17
[parent_id] => 15
[ownerEntityId] =>
[userId] => 2
)
[1] => Array
(
[id] => 18
[parent_id] => 15
[ownerEntityId] =>
)
[2] => Array
(
[id] => 19
[parent_id] => 15
[ownerEntityId] =>
)
)
)
[1] => Array
(
[id] => 11
[parent_id] => 3
[ownerEntityId] =>
)
)
)
[1] => Array
(
[id] => 26
[parent_id] => 1
[ownerEntityId] =>
[children] => Array
(
[0] => Array
(
[id] => 23
[parent_id] => 26
[ownerEntityId] => 24
[1] => Array
(
[id] => 41
[parent_id] => 26
[ownerEntityId] =>
)
)
)
I want this:
Array
(
[0] => Array
(
[id] => 3
[parent_id] => 0
[ownerEntityId] => 2
[show] => true //***Added
[children] => Array
(
[0] => Array
(
[id] => 15
[parent_id] => 3
[ownerEntityId] => 14
[show] => true //***Added
[children] => Array
(
[0] => Array
(
[id] => 17
[parent_id] => 15
[ownerEntityId] =>
[show] => true //***Added
[userId] => 2
)
[1] => Array
(
[id] => 18
[parent_id] => 15
[ownerEntityId] =>
)
[2] => Array
(
[id] => 19
[parent_id] => 15
[ownerEntityId] =>
)
)
)
[1] => Array
(
[id] => 11
[parent_id] => 3
[ownerEntityId] =>
)
)
)
[1] => Array
(
[id] => 26
[parent_id] => 1
[ownerEntityId] =>
[children] => Array
(
[0] => Array
(
[id] => 23
[parent_id] => 26
[ownerEntityId] => 24
[1] => Array
(
[id] => 41
[parent_id] => 26
[ownerEntityId] =>
)
)
)
I have been messing with multiple recursion functions that have failed me miserably.
https://ideone.com/HoJPry
function hasUserId (&$el) {
if(isset($el['children'])) {
$ret = false;
foreach($el['children'] as &$child) {
if(hasUserId($child)) {
$ret=true;
}
}
if($ret) {
$el['show']=true;
return true;
}
} ;
if (isset($el['user_id'])) {
$el['show']=true;
return true;
}
}
foreach($top as $i => $t)
{
foreach($t['children'] as $n => $mid)
{
foreach($mid['children'] as $x => $bottom)
{
if($bottom['id'] !== $target_id)
continue;
$top[$i]['show'] = true;
$top[$i]['children'][$n]['show'] = true;
$top[$i]['children'][$n]['children'][$x]['show'] = true;
}
}
}

convert flat array into multidimensional array in php

I am trying to convert a flat array into multidimensional array based on 'parent' and look a lot of examples and get good results but have 1 issue. I am missing last time of the array.
first i created an flat array
$service_arr = array();
foreach( $order_info[0]['service'] as $ordered_service ) {
$s_id = $ordered_service['id'];
$s_name = $ordered_service['name'];
$s_qty = $ordered_service['qty'];
$s_price = $ordered_service['price'];
$s_parent = gp_get_item_parent( $s_id ); // return parent_id of the element.
$service_arr[] = array(
'id' => $s_id,
'name' => $s_name,
'qty' => $s_qty,
'price' => $s_price,
'parent' => $s_parent
);
}
and this return's a flat array
Result:
Array
(
[0] => Array
(
[id] => 29
[name] => Another Facial
[qty] => 1
[price] => 1800
[parent] => 16
)
[1] => Array
(
[id] => 17
[name] => Facial 1
[qty] => 1
[price] => 2000
[parent] => 16
)
[2] => Array
(
[id] => 26
[name] => Addon
[qty] => 1
[price] => 500
[parent] => 17
)
[3] => Array
(
[id] => 39
[name] => Another Addon
[qty] => 1
[price] => 150
[parent] => 17
)
[4] => Array
(
[id] => 18
[name] => Facial 2
[qty] => 1
[price] => 2000
[parent] => 16
)
[5] => Array
(
[id] => 38
[name] => Nice Facial
[qty] => 1
[price] => 3000
[parent] => 16
)
[6] => Array
(
[id] => 21
[name] => Massage 2
[qty] => 1
[price] => 6000
[parent] => 14
)
)
Converting flat into multidimension array:
function create_tree_array( &$list, &$output, $parent_id ) {
if ( ! is_array( $list ) ) {
return;
}
if ( ! is_array( $output ) ) {
return;
}
foreach( $list as $i => $item ) {
if ( $item['parent'] == $parent_id ) {
$item['addon'] = array();
create_tree_array( $list, $item['addon'], $item['id'] );
$output[] = $item;
}
}
}
And using this function like
$services_tree = array();
create_tree_array( $service_arr, $services_tree, $service_arr[0]['parent'] );
Its working but the issue is that its missing last item of array:
[6] => Array (
[id] => 21
[name] => Massage 2
[qty] => 1
[price] => 6000
[parent] => 14
)

how to make incremental value in hierarchal array in Php?

Hi guys I was wondering how can I add a incremental all elements? Because as of now I am not sure where can I include the "inc" in all elements
Ex:
MY_ARRAY = (
[id] => 4
[children] => Array
(
[0] => Array
(
[id] => 18
[children] => Array
(
[0] => Array
(
[id] => 21
)
[1] => Array
(
[id] => 22
)
)
)
[1] => Array
(
[id] => 19
)
[2] => Array
(
[id] => 20
[children] => Array
(
[0] => Array
(
[id] => 26
)
)
)
)
)
Using these code:
$in = MY_ARRAY
function generateArray($in, $parent = 0){
foreach ($in as $key => $value) {
if(is_numeric($key)){
$in = $value;
$out[$key] = $this->generateArray($in, $parent);
}else{
$out[$key]=$value;
if($key=="id"){
$out['p_id'] = $parent;
$parent=$value;
}elseif($key=="children"){
$in = $value;
$out[$key] = $this->generateArray($in, $parent);
}
}
}
return $out;
}
Will give me this output, not including the [inc].
[id] => 4
[P_id] => 0
[inc] => 1
[children] => Array
(
[0] => Array
(
[id] => 18
[P_id] => 4
[inc] => 2
[children] => Array
(
[0] => Array
(
[id] => 21
[P_id] => 18
[inc] => 3
)
[1] => Array
(
[id] => 22
[P_id] => 18
[inc] => 4
)
)
)
[1] => Array
(
[id] => 19
[P_id] => 4
[inc] => 5
)
[2] => Array
(
[id] => 20
[P_id] => 4
[inc] => 6
[children] => Array
(
[0] => Array
(
[id] => 26
[P_id] => 20
[inc] => 7
)
)
)
)
)
Now I'm not sure where and how can I include the [inc] or the incremental value of each element in the array using my code above.
Need really help here guys...

how to get array like this?

I have one array in php like this :
Array
(
[0] => Array
(
[name] => abc
[id] => 107
[CycleNumber] => 1
[Type] => People
)
[1] => Array
(
[name] => john
[id] => 312
[CycleNumber] => 5
[Type] => People
)
[2] => Array
(
[name] => jenny
[id] => 110
[CycleNumber] => 3
[Type] => People
)
[3] => Array
(
[name] => metting room
[id] => 590
[CycleNumber] => 4
[Type] => Facility
)
[4] => Array
(
[name] => projector
[id] => 470
[CycleNumber] => 4
[Type] => Facility
)
)
I want to replace the duplicate type with blank. but the first one should have that type name and others should have blank. so the result array should be like this :
Array
(
[0] => Array
(
[name] => abc
[id] => 107
[CycleNumber] => 1
[Type] => People
)
[1] => Array
(
[name] => john
[id] => 312
[CycleNumber] => 5
[Type] =>
)
[2] => Array
(
[name] => jenny
[id] => 110
[CycleNumber] => 3
[Type] =>
)
[3] => Array
(
[name] => metting room
[id] => 590
[CycleNumber] => 4
[Type] => Facility
)
[4] => Array
(
[name] => projector
[id] => 470
[CycleNumber] => 4
[Type] =>
)
)
I want array in this format only. and i am using PHP zend.
I search for this but most of them showing to remove that element from array. but i don't want to remove it. i want to replace it with blank but want to show the first one.
Tried Code
$result = array();
$result1 = array();
$result2 = array();
$y = array();
$y1 = array();
foreach ($data as $entry) {
$type= $entry["type"];
if (!isset($y[$type])) {
$y[$type] = array();
unset($entry["type"]);
$result[$type][] = $entry;
}
}
can anyone tell me how to do that ?
Code
$i = 0;
$found = 0;
foreach($data as $key=>&$val) {
if($i != 0) {
if($data[$i]['Type'] == $data[$found]['Type']) {
$data[$i]['Type'] = "";
}
else {
$found = $i;
}
}
$i++;
}
echo "<pre>";
print_r($data);
Output
Array
(
[0] => Array
(
[name] => abc
[id] => 107
[CycleNumber] => 1
[Type] => People
)
[1] => Array
(
[name] => john
[id] => 312
[CycleNumber] => 5
[Type] =>
)
[2] => Array
(
[name] => jenny
[id] => 110
[CycleNumber] => 3
[Type] =>
)
[3] => Array
(
[name] => metting room
[id] => 590
[CycleNumber] => 4
[Type] => Facility
)
[4] => Array
(
[name] => projector
[id] => 470
[CycleNumber] => 4
[Type] =>
)
)
Example

Categories