PHP - UNSET Elements in a Deep Mixed Index/Associative Array - php

I have a mixed index/associative array in PHP that can, in theory, be infinitely deep because some elements may have 'children' arrays. I attach a slimmed down example. The php array is derived from some JSON data.
I want to search on a given key/value pair and to delete any elements matching that pair at the index level.
So for example, in the array below, I wish to search for the key of 'formId' and a value of '44' and to delete elements such that $array[0][0][0][0] and $array[0][1] are removed. Obviously I will then need to re-number the array.
I need to be able to search on any key/value pair... only one pair at a time is necessary... that is to say that the above example of 'formId' of '44' might be 'viewId' of '16' next time.
I have tried numerous ways to do this, with iterators, recursive foreach loops, &$reference keys but I just cannot seem to get it right.
Array
(
[0] => Array
(
[formId] => 0
[subId] => 0
[viewId] => 0
[id] => 0
[children] => Array
(
[0] => Array
(
[formId] => 1
[subId] => 0
[viewId] => 16
[id] => _st_node_5328_0_0
[children] => Array
(
[0] => Array
(
[formId] => 1
[subId] => 0
[viewId] => 16
[id] => _st_node_3838_0_0_0
[children] => Array
(
[0] => Array
(
[formId] => 44
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_0
)
[1] => Array
(
[formId] => 7
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_1
)
[2] => Array
(
[formId] => 3
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_2
)
[3] => Array
(
[formId] => 10
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_3
)
[4] => Array
(
[formId] => 9
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_4
)
[5] => Array
(
[formId] => 8
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_5
)
[6] => Array
(
[formId] => 6
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_6
)
[7] => Array
(
[formId] => 5
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_7
)
[8] => Array
(
[relId] => 167
[formId] => 4
[text] => Laptop Computers
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_8
[isActive] =>
)
[9] => Array
(
[formId] => 1
[subId] =>
[viewId] => 16
[id] => _st_node_947_0_0_0_9
)
)
)
[1] => Array
(
[formId] => 1
[subId] => 0
[viewId] => 1
[id] => _st_node_3838_0_0_1
)
[2] => Array
(
[formId] => 1
[subId] => 0
[viewId] => 11
[id] => _st_node_3838_0_0_2
)
[3] => Array
(
[formId] => 1
[subId] => 0
[viewId] => 12
[id] => _st_node_3838_0_0_3
)
[4] => Array
(
[formId] => 1
[subId] => 0
[viewId] => 13
[id] => _st_node_3838_0_0_4
)
[5] => Array
(
[formId] => 1
[subId] => 0
[viewId] => 14
[id] => _st_node_3838_0_0_5
)
[6] => Array
(
[formId] => 1
[subId] => 0
[viewId] => 110
[id] => _st_node_3838_0_0_6
)
)
)
[1] => Array
(
[formId] => 44
[subId] => 0
[viewId] => 144
[id] => _st_node_5328_0_1
)
[2] => Array
(
[formId] => 10
[subId] => 0
[viewId] => 26
[id] => _st_node_5328_0_2
)
[3] => Array
(
[formId] => 9
[subId] => 0
[viewId] => 9
[id] => _st_node_5328_0_3
)
[4] => Array
(
[formId] => 8
[subId] => 0
[viewId] => 8
[id] => _st_node_5328_0_4
)
[5] => Array
(
[formId] => 7
[subId] => 0
[viewId] => 25
[id] => _st_node_5328_0_5
)
[6] => Array
(
[formId] => 6
[subId] => 0
[viewId] => 6
[id] => _st_node_5328_0_6
)
[7] => Array
(
[formId] => 5
[subId] => 0
[viewId] => 5
[id] => _st_node_5328_0_7
)
[8] => Array
(
[formId] => 4
[subId] => 0
[viewId] => 4
[id] => _st_node_5328_0_8
)
[9] => Array
(
[formId] => 3
[subId] => 0
[viewId] => 3
[id] => _st_node_5328_0_9
)
)
)
)

The idea
Since you want to unset elements, you definitely want to pass the $array into the function as a reference (&$array).
You want to use recursion to allow you to dig as deep as necessary based on the actual array.
You loop over all elements of the array and the first thing you do is check whether an element is an array. If it is, you check if that subarray matches your criteria. If it does, you remove it. If it doesn't you invoke the function with the same $key, $value pair on that subarray.
The code
function removeMatching($key, $value, &$arr) {
// Iterate over all $arr elements
foreach ($arr as $i => $subarr) {
// Skip all elements that are not arrays
if (is_array($subarr)) {
// Check if the sub-array matches the criteria
if (isset($subarr[$key]) && $subarr[$key] === $value) {
// Remove it from the main array if it does
unset($arr[$i]);
} else {
// If the sub-array didn't match the criteria
// Check if it contains any other matching sub-arrays
removeMatching($key, $value, $arr[$i]);
}
}
}
}
Apply like this:
$array = []; // your array
removeMatching('formId', 44, $array);
var_dump($array);

Related

PHP Subtract multidimensional arrays based on 2 values

I need to subtract the qt from two arrays based on id and type, keeping the array complete.
How do I do in php to be able to subtract these arrays?
I have 2 arrays:
=> this is the first array with multiple key "down"
Array
(
[0] => Array
(
[id] => 26
[loc] => 1
[type] => down
[qt] => 12
)
[1] => Array
(
[id] => 32
[loc] => 1
[type] => down
[qt] => 34
)
[2] => Array
(
[id] => 26
[loc] => 2
[type] => down
[qt] => 5
)
[3] => Array
(
[id] => 86
[loc] => 3
[type] => down
[qt] => 45
)
[4] => Array
(
[id] => 23
[loc] => 9
[type] => down
[qt] => 3
)
[5] => Array
(
[id] => 23
[loc] => 3
[type] => down
[qt] => 99
)
)
=> this is the second array with multiple key "up"
Array
(
[0] => Array
(
[id] => 26
[loc] => 1
[type] => up
[qt] => 5
)
[1] => Array
(
[id] => 86
[loc] => 3
[type] => up
[qt] => 27
)
[2] => Array
(
[id] => 23
[loc] => 9
[type] => up
[qt] => 3
)
)
=> I need cubtract "qt" (if "id" and "loc" are the same then subtract the "qt")
Array
(
[0] => Array
(
[id] => 26
[loc] => 1
[type] => total
[qt] => 7
)
[1] => Array
(
[id] => 32
[loc] => 1
[type] => total
[qt] => 34
)
[2] => Array
(
[id] => 26
[loc] => 2
[type] => total
[qt] => 5
)
[3] => Array
(
[id] => 86
[loc] => 3
[type] => total
[qt] => 18
)
[4] => Array
(
[id] => 23
[loc] => 9
[type] => total
[qt] => 0
)
[5] => Array
(
[id] => 23
[loc] => 3
[type] => down
[qt] => 99
)
)
Try this out
function findMatch($array, $id, $loc)
{
foreach ($array as $key => $item) {
if ($item["id"] == $id and $item["loc"] == $loc) {
return $key;
}
}
return false;
}
$total = [];
foreach($down as $d) {
$matched = findMatch($up, $d["id"], $d["loc"]);
if($matched !== false){
$total[] = array_replace($d, [
"type" => "total",
"qt" => ($d["qt"] - $up[$matched]["qt"])
]);
} else {
$total[] = array_replace($d, ["type" => "total"]);
}
}
print_r($total);

Sort a multidimensional an array with numeric keys but keep the keys same just change the order [duplicate]

This question already has an answer here:
PHP sort associative array by numeric key in asc order [duplicate]
(1 answer)
Closed 10 months ago.
So I have 3 dimensional array. I want that array to be reordered based on the keys but the value of the keys should remain as it is. Like for an example if the array keys are 5,2,4,1,3 then it should become 1,2,3,4,5. Below I'm providing the array I have and excepted array and the solutions I have tried.
This is the array I have :-
[5] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => E3
[deal_text] =>
[units] => 5
[total_units] => 5
[amount] => 2620.8333333333
[is_freezed] =>
[can_sell] => 1
)
)
)
[2] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => E4
[deal_text] =>
[units] => 1
[total_units] => 0
[amount] => 516.66666666667
[is_freezed] => 1
[can_sell] =>
)
)
)
[4] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => C8
[deal_text] =>
[units] => 1
[total_units] => 0
[amount] => 526.66666666667
[is_freezed] => 1
[can_sell] =>
)
)
)
[1] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => D4
[deal_text] =>
[units] => 1
[total_units] => 0
[amount] => 557.14285714286
[is_freezed] => 1
[can_sell] =>
)
)
)
[3] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => E5
[deal_text] =>
[units] => 1
[total_units] => 0
[amount] => 516.66666666667
[is_freezed] => 1
[can_sell] =>
)
)
)
Following are the solutions I have tried :-
$result = ksort($result);
$result = array_values($result);
$result = array_splice($result, 0, 0);
$result = sort($result);
$result = array_splice($result, 0, count($result));
This is the expected array :-
Array
(
[1] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => D4
[deal_text] =>
[units] => 1
[total_units] => 0
[amount] => 557.14285714286
[is_freezed] => 1
[can_sell] =>
)
)
)
[2] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => E4
[deal_text] =>
[units] => 1
[total_units] => 0
[amount] => 516.66666666667
[is_freezed] => 1
[can_sell] =>
)
)
)
[3] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => E5
[deal_text] =>
[units] => 1
[total_units] => 0
[amount] => 516.66666666667
[is_freezed] => 1
[can_sell] =>
)
)
)
[4] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => C8
[deal_text] =>
[units] => 1
[total_units] => 0
[amount] => 526.66666666667
[is_freezed] => 1
[can_sell] =>
)
)
)
[5] => Array
(
[Anfield] => Array
(
[0] => Array
(
[slot] => E3
[deal_text] =>
[units] => 5
[total_units] => 5
[amount] => 2620.8333333333
[is_freezed] =>
[can_sell] => 1
)
)
)
)
Nothing is working any help will be appreciated. thanks in advance.
You are using ksort as $result = ksort($result);, ksort return TRUE/FALSE. That means you are assigning that to $results.
Read here PHP ksort
Your code should be:-
ksort($results);
instead of
$result = ksort($result);
You can use ksort for the keys sorting, here is an example
$arr = [
5 => [1,3],
3 => [2,3],
2 => [0,7]
];
ksort($arr);
echo '<pre>';
print_r($arr);
Output
Array
(
[2] => Array
(
[0] => 0
[1] => 7
)
[3] => Array
(
[0] => 2
[1] => 3
)
[5] => Array
(
[0] => 1
[1] => 3
)
)

Joining two multidimensional arrays

I have two arrays each coming from different DB queries, I can't join them in DB so I have to join them using php.
The first:
Array
(
[0] => Array
(
[id] => 23
[host_id] => 5
[pos_id] => 2
[status] => 1
)
[1] => Array
(
[id] => 25
[host_id] => 5
[pos_id] => 1
[status] => 1
)
[2] => Array
(
[id] => 24
[host_id] => 5
[pos_id] => 2
[status] => 1
)
)
And I wanna join it with this array on pos_id and id
Array
(
[0] => Array
(
[id] => 1
[name] => Front
)
[1] => Array
(
[id] => 2
[name] => Back
)
)
so that, the result is:
Array
(
[0] => Array
(
[id] => 23
[host_id] => 5
[pos_id] => 2
[name] => Back
[status] => 1
)
[1] => Array
(
[id] => 25
[host_id] => 5
[pos_id] => 1
[name] => Front
[status] => 1
)
[2] => Array
(
[id] => 24
[host_id] => 5
[pos_id] => 2
[name] => Back
[status] => 1
)
)
The code I have uses an inner loop, matches the value and pushes into array:
foreach($events as &$event) {
foreach($positions as $position) {
if($player[pos_id] == $position[id]){
array_push($event,"name",$position[name]);
}
}
}

PHP sum array values with same keys

This is the original main array:
Array
(
[0] => Array
(
[subtotal] => 0.6000
[taxes] => 0.0720
[charged_amount] => 0.6720
[total_discount] => 0.0000
[provinceName] => BC
[store_key] => 1
[store_id] => 5834
[categories] => Array
(
[2] => 0.6000
[4] => 0
[3] => 0
)
)
[1] => Array
(
[subtotal] => 29.8500
[taxes] => 2.3270
[charged_amount] => 20.2370
[total_discount] => 11.9400
[provinceName] => MB
[store_key] => 9
[store_id] => 1022
[categories] => Array
(
[2] => 0
[4] => 29.8500
[3] => 0
)
)
[2] => Array
(
[subtotal] => 0.3000
[taxes] => 0.0390
[charged_amount] => 0.3390
[total_discount] => 0.0000
[provinceName] => NB
[store_key] => 8
[store_id] => 1013
[categories] => Array
(
[2] => 0.3000
[4] => 0
[3] => 0
)
)
[3] => Array
(
[subtotal] => 24.3100
[taxes] => 1.1830
[charged_amount] => 10.2830
[total_discount] => 15.2100
[provinceName] => NL
[store_key] => 4
[store_id] => 3033
[categories] => Array
(
[2] => 24.3100
[4] => 0
[3] => 0
)
)
[4] => Array
(
[subtotal] => 1116.3400
[taxes] => 127.6960
[charged_amount] => 1110.0060
[total_discount] => 134.0300
[provinceName] => ON
[store_key] => 2
[store_id] => 1139
[categories] => Array
(
[2] => 85.7300
[4] => 143.2800
[3] => 887.3300
)
)
[5] => Array
(
[subtotal] => 10.8500
[taxes] => 1.4100
[charged_amount] => 12.2600
[total_discount] => 0.0000
[provinceName] => ON
[store_key] => 5
[store_id] => 1116
[categories] => Array
(
[2] => 10.8500
[4] => 0
[3] => 0
)
)
)
I just need to add the values of the array [categories] with same keys and use it further to print the total, but not getting correct output, can someone help me out to get the desired result:
Desired result
An array with same keys but total of individual array values
Array ( [2] => 0.9000 [4] => 29.8500 [3] => 1.5 )
NOTE: Initial array is dynamic can have n number of key value pair
Thanks
The first thing that you need to do is iterate through the outer array. Then, for each row in the outer array, you and to iterate through each entry in the category element. So this means that we have two foreach loops. Inside the inner foreach, we simply set the value for the current index to be the value of the same index on a 'sum' array (if it doesn't already exist), or increment the value of that index if it already exists in the 'sum' array.
<?php
$sumArray = array();
foreach($outerArray as $row)
{
foreach($row["categories"] as $index => $value)
{
$sumArray[$index] = (isset($sumArray[$index]) ? $sumArray[$index] + $value : $value);
}
}
?>
Demo using your example array

PHP array_merge not doing exactly what i need it to do

Ok so here is my first array:
(
[1] => Array
(
[27] => Array
(
[product_id] => 27
[type] => hardware
[step_number] => 1
)
[372] => Array
(
[product_id] => 372
[type] => hardware
[step_number] => 1
)
[92] => Array
(
[product_id] => 92
[type] => hardware
[step_number] => 1
)
)
[2] => Array
(
[335] => Array
(
[product_id] => 335
[type] => hardware
[step_number] => 2
)
[62] => Array
(
[product_id] => 62
[type] => hardware
[step_number] => 2
)
[356] => Array
(
[product_id] => 356
[type] => hardware
[step_number] => 2
)
)
and here is my second array
(
[1] => Array
(
[655] => Array
(
[product_id] => 655
[type] => optional
[step_number] => 1
)
[54] => Array
(
[product_id] => 54
[type] => optional
[step_number] => 1
)
[554] => Array
(
[product_id] => 554
[type] => optional
[step_number] => 1
)
)
[2] => Array
(
[33] => Array
(
[product_id] => 33
[type] => optional
[step_number] => 2
)
[612] => Array
(
[product_id] => 612
[type] => optional
[step_number] => 2
)
[5] => Array
(
[product_id] => 5
[type] => optional
[step_number] => 2
)
)
[3] => Array
(
[444] => Array
(
[product_id] => 444
[type] => optional
[step_number] => 3
)
[6] => Array
(
[product_id] => 6
[type] => optional
[step_number] => 3
)
[53] => Array
(
[product_id] => 53
[type] => optional
[step_number] => 3
)
)
Basically what i need is the second array appended to the end of the first array with the keys of the first array preserved the keys and changing the step_number to the new key so the final keys looks like
(
[1] => Array
(
[27] => Array
(
[step_number] => 1)
....
[2] => Array
(
[335] => Array
(
[step_number] => 2)
....
[3] => Array
(
[655] => Array
(
[step_number] => 3)
....
[4] => Array
(
[33] => Array
(
[step_number] => 4)
....
[5] => Array
(
[444] => Array
(
[step_number] => 5)
....
but when i do
$all = array_merge($first, $second);
the keys are
(
[0] => Array
[1] => Array
[2] => Array
[3] => Array
[4] => Array
Is that possible to do....
Try array_merge_recursive .. http://php.net/array_merge_recursive
This is also from the manual on array_splice if you're just looking to append your 2nd array onto the first (http://php.net/manual/en/function.array-push.php):
array_splice($first, count($first), 0, $second);
Iterating over the first set of keys, then using the Union array operator should do the trick.
//$first = array(...);
//$second = array(...);
foreach ($second as $key => $value)
{
if (!isset($first[$key]))
{
$first[$key] = array();
}
$first[$key] += $value;
}

Categories