convert nested foreach tree into recursive php function - php

Need to make recursive function from the below code. tried multiple ways but failed. because I don't know how much depth will the tree have. depth may be varying according to the data.
$tot_terms = [];
foreach ($tree as $key => $val) {
$tot_terms[$val->depth][] = $val->tid;
if (!empty($val->children)) {
foreach ($val->children as $key1 => $val1) {
$tot_terms[$val1->depth][] = $val1->tid;
if ($val1->children) {
foreach ($val1->children as $key2 => $val2) {
$tot_terms[$val2->depth][] = $val2->tid;
if ($val2->children) {
foreach ($val2->children as $key3 => $val3) {
$tot_terms[$val3->depth][] = $val3->tid;
if ($val3->children) {
foreach ($val3->children as $key4 => $val4) {
$tot_terms[$val4->depth][] = $val4->tid;
if ($val4->children) {
foreach ($val4->children as $key5 => $val5) {
$tot_terms[$val5->depth][] = $val5->tid;
}
}
}
}
}
}
}
}
}
}
}
and the result should be like this
Array
(
[0] => Array
(
[0] => 20011
[1] => 19991
[2] => 20000
)
[1] => Array
(
[0] => 20010
[1] => 19995
[2] => 19994
[3] => 19990
[4] => 20005
[5] => 19985
[6] => 19999
[7] => 19998
)
[2] => Array
(
[0] => 20012
[1] => 20006
[2] => 19996
[3] => 19993
[4] => 19989
[5] => 19988
[6] => 20004
[7] => 19984
[8] => 20001
)
[3] => Array
(
[0] => 20007
[1] => 20009
[2] => 20008
[3] => 19992
[4] => 19987
[5] => 19986
[6] => 19983
[7] => 19982
[8] => 20003
[9] => 20002
)
[4] => Array
(
[0] => 19997
)
[5] => Array
(
[0] => 19981
)
)
Tried according to other post but it is failing. input $tree is something that is array and an object. will post in next comment if required as total body count is more than its expected

We can use a handler function to store data. Note that we are passing the array by reference.
function func( $item, &$data ) {
if ( is_empty( $item ) ) return;
if ( ! is_object( $item ) ) return;
foreach ($item as $key => $val) {
$data[$val->depth][] = $val->tid;
func( $val->children, $data );
}
}
function func_handler( $item ) {
$data = [];
func( $item, $data );
return $data;
}

Related

Convert PHP array to new data-structure

I have a MYSQL query which returns the following PHP array $result:
[0] => Array (
[resourceKey] => cloth
[date] => 2020-09-06
[quantity] => 8
)
[1] => Array (
[resourceKey] => ebony
[date] => 2020-09-06
[quantity] => 4
)
[2] => Array (
[resourceKey] => gems
[date] => 2020-09-06
[quantity] => 0
)
[3] => Array (
[resourceKey] => lead
[date] => 2020-09-06
[quantity] => 0
)
[4] => Array (
[resourceKey] => limestone
[date] => 2020-09-06
[quantity] => 8
)
[5] => Array (
[resourceKey] => cloth
[date] => 2020-09-05
[quantity] => 6
)
[6] => Array (
[resourceKey] => ebony
[date] => 2020-09-05
[quantity] => 3
)
[7] => Array (
[resourceKey] => gems
[date] => 2020-09-05
[quantity] => 0
)
[8] => Array (
[resourceKey] => lead
[date] => 2020-09-05
[quantity] => 0
)
[9] => Array (
[resourceKey] => limestone
[date] => 2020-09-05
[quantity] => 6
)
And I need to convert it is a certain way to display it with jquery Datatables:
$data= array(
array("Date" => "2020-09-05","cloth"=>"6","ebony"=>"3","gems"=>"0","lead"=>"0","limestone"=>"6"),
array("Date" => "2020-09-06","cloth"=>"8","ebony"=>"4","gems"=>"0","lead"=>"0","limestone"=>"8")
);
I've been trying for a while now but can't get a good way to iterate through the results...
I have already taken care of building the columns to pass to Datatables:
$columns = array();
$columns[] = array('data' => 'Date', 'title' => 'Date');
foreach ($result as $key => $row_data) {
$newResourceKey = $myUtilities->in_array_recursive($row_data['resourceKey'], $columns);
if ($newResourceKey === FALSE) { // Only if column name not yet in array
$columns[] = array('data' => $row_data['resourceKey'], 'title' => $row_data['resourceKey']);
}
}
This is an example of the many things I've tried:
$isDateInArray = $myUtilities->in_array_recursive($row_data['date'], $data);
if ($isDateInArray === FALSE) { // Only if Date is not in array yet
array_push($data, array('Date' => $row_data['date'], $row_data['resourceKey'] => $row_data['quantity'])); // Push date and data
}
else {
array_push($data, array($row_data['resourceKey'] => $row_data['quantity'])); // Only push data. Can't find a way to add it to existing Date array
}
Update:
public function in_array_recursive($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && $this->in_array_recursive($needle, $item, $strict))) {
return true;
}
}
return false;
}
You can get the desired result by next simple array transformation:
$res = [];
foreach ($result as $row) {
$res[$row['date']][$row['resourceKey']] = $row['quantity'];
}
$final = [];
foreach ($res as $d=>$r) {
array_push($final, array_merge(['date'=>$d], $r));
}
print_r($final);
Here you can try the PHP code

how to array push with multidimension in php

I have an array in PHP loop output like this
this is my php code :
$sql = "SELECT * FROM `acc` ";
$stm = $conn->prepare($sql);
$stm->execute();
$array= [];
while ($row = $stm->fetch(PDO::FETCH_ASSOC)) {
$array[]=$row['h_id'];
}
print_r($array);
and output is :
Array
( [0] => 11
[1] => 12
[2] => 13
[3] => 1101
[4] => 1102
[5] => 110101
[6] => 110102
[7] => 1201
[8] => 1202
[9] => 1301
[10] => 1302
[11] => 1303
[12] => 130201
[13] => 130202
[14] => 130301
[15] => 130302
)
and I want to sort and rearrange array to multi-dimension for parent and child with php Loop Like this :
Array
(
[11] => Array
(
[1101] => Array
(
[0] => 110101
[1] => 110102
)
)
[12] => Array
(
[0] => 1201
[1] => 1202
)
[13] => Array
(
[0] => 1301
[1302] => Array
(
[0] => 130201
[1] => 130202
)
[1303] => Array
(
[0] => 130301
[1] => 130302
)
)
how to implemention and push array to another with php.
thanks!
I absolutely don't understand what you're doing, but I think I've grasped how your input may be mapped to desired output. Here is the code:
<?php
$flat = [
11,
12,
13,
1101,
1102,
110101,
110102,
1201,
1202,
1301,
1302,
1303,
130201,
130202,
130301,
130302,
];
function expand($flat)
{
$expanded = [];
foreach ($flat as $element) {
$sections = str_split((string)$element, 2);
$tmp = &$expanded;
$path = '';
foreach ($sections as $section) {
$path .= $section;
if (!isset($tmp[$path])) {
$tmp[$path] = [];
}
$tmp =& $tmp[$path];
}
unset($tmp);
}
return $expanded;
}
function fold($expanded) {
$folded = [];
foreach ($expanded as $key => $value) {
if ($value === []) {
$folded[] = $key;
} else {
$folded[$key] = fold($value);
}
}
return $folded;
};
print_r(fold(expand($flat)));
And here is its output (which is suspiciously close to yours):
Array
(
[11] => Array
(
[1101] => Array
(
[0] => 110101
[1] => 110102
)
[1102] => 1102
)
[12] => Array
(
[0] => 1201
[1] => 1202
)
[13] => Array
(
[0] => 1301
[1302] => Array
(
[0] => 130201
[1] => 130202
)
[1303] => Array
(
[0] => 130301
[1] => 130302
)
)
)
There are some differences, though, e.g. there is element 1102 in your input, but in your sample output it is absent, and I'm not sure if you forgot it or if you have filtered it out for some reason.

Remove internal array in php

I have to remove an internal array from an array. Actually, the array is obtained by decoding JSON, and can go upto n levels. I need to remove an internal array from an array of its parent based on the key which is dynamic. Below is the code that I have tried referring to answers on php arrays.
$quotationHistory = json_decode($quotationCollection->getHistory(), true);
$quotationId = 5;
foreach ($quotationHistory as $sales_id => $history) {
foreach($history as $quotationIdValue => $values) {
if ($quotationId == $quotationIdValue) {
unset ($history[$quotationIdValue]);
}
}
}
sample:
Array
(
[1] => Array
(
[5] => Array
(
[0] => Array
(
[0] => 3
[1] => 8490.0000
[2] => 21-10-2016 11:43:18am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
[1] => Array
(
[0] => 12
[1] => 8490.0000
[2] => 21-10-2016 11:43:40am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
[2] => Array
(
[0] => 45
[1] => 8490.0000
[2] => 21-10-2016 11:43:54am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
[3] => Array
(
[0] => 11
[1] => 8490.0000
[2] => 21-10-2016 11:44:04am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
[4] => Array
(
[0] => 54
[1] => 8490.0000
[2] => 21-10-2016 11:44:16am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
)
)
)
Now, I want to remove the second level data with key = 5
You'd better do the unset on the original array:
$quotationHistory = json_decode($quotationCollection->getHistory(), true);
foreach($quotationHistory as $sales_id => $history) {
foreach($history as $quotationIdValue => $values) {
if($quotationId == $quotationIdValue){
unset($quotationHistory[$sales_id][$quotationIdValue]);
}
}
}
The reason is that the internal array is passed as a copy. But you can also specify an assignation by reference:
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference (official Php doc).
$quotationHistory = json_decode($quotationCollection->getHistory(), true);
foreach($quotationHistory as $sales_id => &$history) {
foreach($history as $quotationIdValue => &$values) {
if($quotationId == $quotationIdValue){
unset($$history[$quotationIdValue]);
}
}
}
You will probably want a recursive iterator since the return can be any level down in the array (presumably that's what you mean by n levels). One note, it would remove any key with the same value so it would remove any key with 5. You would be better to recurse to remove the key based on value rtg:
$arr = array(
'one'=>array(
'one'=>'and a half',
'two'=>array(
'three'=>'three and a half'
)
)
);
function recurse($array,$remove=false)
{
foreach($array as $key => $value) {
if($key != $remove){
if(is_array($value)) {
$new[$key] = recurse($value,$remove);
}
else
$new[$key] = $value;
}
}
return $new;
}
# Run the iterator to remove the key named "three"
print_r(recurse($arr,'three'));
If you need to search by value, this should work:
function recurseValue($array,$remove=false)
{
foreach($array as $key => $value) {
if(is_array($value)) {
$new[$key] = recurseValue($value,$remove);
}
else {
if($value != $remove){
$new[$key] = $value;
}
}
}
return $new;
}
# Run the iterator to remove the key with the value named "Three and a half"
print_r(recurseValue($arr,'three and a half'));
Gives you:
Array
(
[one] => Array
(
[one] => and a half
[two] =>
)
)
This last option will normalize the array to one level so you can loop over it normally:
function recurseArray($array,&$new,$bkey = false)
{
foreach($array as $key => $value) {
if(is_array($value)) {
recurseArray($value,$new,$key);
}
else {
$new[$bkey][] = $value;
}
}
}
$new = array();
recurseArray($arr,$new);
print_r($new);
Gives you:
Array
(
[0] => Array
(
[0] => 3
[1] => 8490.0000
[2] => 21-10-2016 11:43:18am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
[1] => Array
(
[0] => 3
[1] => 8490.0000
[2] => 21-10-2016 11:43:18am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
[2] => Array
(
[0] => 3
[1] => 8490.0000
[2] => 21-10-2016 11:43:18am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
[3] => Array
(
[0] => 3
[1] => 8490.0000
[2] => 21-10-2016 11:43:18am
[3] => 24-11-2016 11:43:18am
[4] => 199
[5] => rtg
)
)

how to sum of two multidimensional array?

I am new in php. i need sum of two arrays but not getting right output.my arrays are coming in this way.
this is my first array.
Array
(
[1] => Array
(
[1] => Array
(
[-10] => 21787048.7293
[-5] => 21816115.9548
[-1] => 21839369.7352
[0] => 21845183.1803
[1] => 21850996.6254
[5] => 21874250.4058
[10] => 21903317.6313
)
)
[2] => Array
(
[2] => Array
(
[-10] => 21147607.6407
[-5] => 21496395.4105
[-1] => 21775425.6263
[0] => 21845183.1803
[1] => 21914940.7343
[5] => 22193970.9501
[10] => 22542758.7199
)
)
)
and this is second array.
Array
(
[1] => Array
(
[1] => Array
(
[-10] => 26101989.9443
[-5] => 26131057.1698
[-1] => 26154310.9501
[0] => 26160124.3952
[1] => 26165937.8403
[5] => 26189191.6207
[10] => 26218258.8462
)
)
[2] => Array
(
[2] => Array
(
[-10] => 25462548.8556
[-5] => 25811336.6254
[-1] => 26090366.8413
[0] => 26160124.3952
[1] => 26229881.9492
[5] => 26508912.1651
[10] => 26857699.9349
)
)
)
i need sum of these two arrays by keys.please help me out.
this is my code.my two arrays are $pretax_income, $earning.
foreach($pretax_income as $k=>$value)
{
foreach($value as $v=>$val)
{
foreach($val as $u=>$valArr) {
$comboarray[$elno] = $valArr[$k][$v][$u] + $earning[$k][$v][$u];
}
}
} print_r($comboarray);
function sum()
{
$identicalKeysArrays = func_get_args();
if (is_array($identicalKeysArrays[0])) {
$result = call_user_func_array('sum', array_map(function ($array) {
return $array[0];
}, $identicalKeysArrays));
if ($result) {
return $result;
}
}
if ($identicalKeysArrays[0]) {
$summed = array();
foreach ($identicalKeysArrays as $array) {
foreach ($array as $key => $value) {
$summed[$key] = ($summed[$key] ? $summed[$key] : 0) + $value;
}
}
return $summed;
}
}
$a = array(array(
'-1' => 23,
'2' => 2
));
$b = array(array(
'-1' => 3
));
var_dump(sum($a, $b));
Result:
array(2) { [-1]=> int(26) [2]=> int(2) }
Maybe something like this?
foreach($pretax_income as $key1=>$val1){
foreach($val1 as $key2=>$val2){
foreach($val2 as $key3=>$val3){
$comboarray[$key1][$key2][$key3]=$pretax_income[$key1][$key2][$key3]+$earning[$key1][$key2][$key3];
}
}
}

Sorting through array for to find match

I have two arrays like this
Array
(
[0] => MYU_MP1
[1] => 4cc00e5f580f00c2e54193fde7129608
[2] => da8bbfdb40be0dc2b3312ca1037f994a
[3] => d4cfaa8db24c4b81db506189360b6b99
)
Array
(
[0] => MYU_SC1
[1] => MYU_SC2
[2] => MYU_SF1
[3] => MYU_SC3
[4] => MYU_AD1
[5] => MYU_AD2
[6] => MYU_AD3
[7] => MYU_AD4
[8] => MYU_RC1
[9] => MYU_RC2
[10] => MYU_RC3
[11] => MYU_RC4
[12] => MYU_RC5
[13] => MYU_RC6
[14] => MYU_RC7
[15] => MYU_RC8
)
the first one aliased as "deliverable" and the other "non_deliverable"
and a third array
Array
(
[d8df18561040f3d9bd9868f5c5aaa7c2] => Array
(
[rowid] => d8df18561040f3d9bd9868f5c5aaa7c2
[id] => MYU_SC1
[qty] => 1
[price] => 500
[name] => WAEC Scratch Card
[service_image] => assets/img/waec.jpg
[service_category] => scratch_cards
[subtotal] => 500
)
the third array is aliased "cart_items"
[f68964856a61092d9a2566d024a0ba28] => Array
(
[rowid] => f68964856a61092d9a2566d024a0ba28
[id] => MYU_MP1
[qty] => 1
[price] => 210000
[name] => Apple iPhone 5 16gb
[service_image] =>
[service_category] => mobile-phones
[subtotal] => 210000
)
)
I have written a function that supposed to loop through the third array to determine if an "id" element of the third array is member of the first or second array
//sort through cart items
foreach ($cart_items as $key => $item) {
if(in_array($item['id'], $deliverables) && in_array($item['id'], $non_deliverables)) {
$deliverable = TRUE;
$non_deliverable = TRUE;
}
if(in_array($item['id'], $deliverables) && !in_array($item['id'], $non_deliverables)) {
$deliverable = TRUE;
}
if(in_array($item['id'], $non_deliverables) && !in_array($item['id'], $deliverables)) {
$non_deliverable = TRUE;
}
if($deliverable && $non_deliverable)
$type = "both";
if($non_deliverable)
$type = "non-deliverable";
if($deliverable)
$type = "deliverable";
}
return $type;
But when the third array has matches in both the 1st and 2nd array the function returns "deliverable". What am i not doing right?
function somefunction()
foreach ($cart_items as $key => $item) {
$deliverable = in_array($item['id'], $deliverables);
$non_deliverable = in_array($item['id'], $non_deliverables);
$type = "none";
if ($deliverable && $non_deliverable) {
$type = "both";
} elseif ($deliverable && !$non_deliverable) {
$type = "deliverable";
} elseif (!$deliverable && $non_deliverable) {
$type = "non-deliverable";
}
}
return $type;
}
Your sortorder is wrong. The check for $deliverable and $non_deliverable should be the last. Alternatively you could use an if-else-if-else structure.

Categories