PHP array key sum value if exist in loop with dynamic value - php

I create of Tree (Bill of Materials) from SQL and i'm make calculation of product. I have few if in if and if in if etc. I want to display sumamry of all individual part number with total quantitny which i'm calculating dynamicly. So, before loop and function if. i'm created three variables:
$TablicaMiH = array();
$TablicaBo = array();
$TablicaAss = array();
when I meet the conditions, which depend on the if function, each of them performs operations of adding to the array. this is:
$TablicaMiH += [$SqlCheckAssyResultShowQ['PartNumber'] => $multipler];
or
$TablicaBo += [$SqlCheckAssyResultShowQ['PartNumber'] => $multipler];
or
$TablicaAssy += [$SqlCheckAssyResultShowQ['PartNumber'] => $multipler];
The commands execute correctly as needed, but they do not add the sum value from the $ multipler variable to me, they only do individual PartNumbers and take the last value from the $ multipler variable
here is the result of what was received from the script:
Tablica MiH:
Array ( [333/E8093] => 2 [332/F2592] => 3 [332/F3144] => 9 [332/F3147] => 21 [332/F2684] => 8 [333/D1641] => 12 [333/D1202] => 22 [332/F2588] => 1 [333/E7883] => 1 [333/E8131] => 1 )
Tablica BO:
Array ( [826/10381] => 12 [331/30854] => 7 [332/F3213] => 4 [123/06090] => 84 [1315/0307Z] => 1 [823/10874] => 1 [333/E7939] => 4 [813/10186] => 2 [332/H3476] => 3 [32/920300] => 11 [332/F3282] => 1 [32/926051] => 1 )
Tablica Ass:
Array ( [2th] => 1 [3TH] => 1 [4th] => 1 [5th] => 1 [6th] => 1 [7th] => 1 [8th] => 1 [9th] => 1 [10Th] => 1 [IN_1TH] => 1 )
and result what i need to have:
$TablicaMiH
332/F2588||5
332/F2592||10
332/F2684||9
332/F3144||27
332/F3147||38
333/D1202||40
333/D1641||16
333/E7883||1
333/E8093||12
333/E8131||1
Tablica BO:
123/06090||85
1315/0307Z||1
32/920300||11
32/926051||1
331/30854||20
332/f3213||29
332/F3282||1
332/H3476||3
333/E7939||4
813/10186||3
823/10874||1
826/10381||13
Tablica Ass:
10Th||1
1TH||1
2TH||1
3TH||1
4th||1
5th||1
6th||1
7th||1
8th||1
9th||1
IN_1TH||1
I Hope you understand me what i mean, and you can help me, thank you
Example to understand my problem:
<?php
$exampleArraY = array(
"PartNumber1" => 1,
"PartNumber2" => 1,
"PartNumber3" => 1,
"PartNumber4" => 1,
"PartNumber5" => 1,
"PartNumber6" => 1,
);
$value = "PartNumber1";
$value2 = "PartNumber2";
$value3 = "PartNumber3";
$value4 = "PartNumber4";
$value5 = "PartNumber5";
$value6 = "PartNumber6";
$value7 = "PartNumber7";
$multipler = 1;
if(in_array($value, $exampleArraY)){
$exampleArraY[$value][1] += $multipler;
}else {
$exampleArraY += [$value => $multipler];
}
if(in_array($value2, $exampleArraY)){
$exampleArraY[$value2][1] += $multipler;
}else {
$exampleArraY += [$value2 => $multipler];
}
if(in_array($value3, $exampleArraY)){
$exampleArraY[$value3][1] += $multipler;
}else {
$exampleArraY += [$value3 => $multipler];
}
if(in_array($value4, $exampleArraY)){
$exampleArraY[$value4][1] += $multipler;
}else {
$exampleArraY += [$value4 => $multipler];
}
if(in_array($value5, $exampleArraY)){
$exampleArraY[$value5][1] += $multipler;
}else {
$exampleArraY += [$value5 => $multipler];
}
if(in_array($value6, $exampleArraY)){
$exampleArraY[$value6][1] += $multipler;
}else {
$exampleArraY += [$value6 => $multipler];
}
if(in_array($value7, $exampleArraY)){
$exampleArraY[$value7][1] += $multipler;
}else {
$exampleArraY += [$value7 => $multipler];
}
print_r($exampleArraY);
?>
Result:
Array ( [PartNumber1] => 1 [PartNumber2] => 1 [PartNumber3] => 1 [PartNumber4] => 1 [PartNumber5] => 1 [PartNumber6] => 1 )
Desired Result:
Array ( [PartNumber1] => 2 [PartNumber2] => 2 [PartNumber3] => 2 [PartNumber4] => 2 [PartNumber5] => 2 [PartNumber6] => 2 [PartNumber7] => 1 )

If I understand the problem correctly, you might be looking for something like this:
// create the starting array
$TablicaMiH = [];
// ... do interesting things... in a loop most likely....
// if we dont have a value for this key yet, set it to 0
if (!isset($TablicaMiH[$SqlCheckAssyResultShowQ['PartNumber']])) {
$TablicaMiH[$SqlCheckAssyResultShowQ['PartNumber']] = 0;
}
// now add the multiplier for this part number
$TablicaMiH[$SqlCheckAssyResultShowQ['PartNumber']] += $multipler;

The problem like i explained was in construction of arrays. Here is my solution to your problem:
<?php
$exampleArraY = array(
"PartNumber1" => 1,
"PartNumber2" => 1,
"PartNumber3" => 1,
"PartNumber4" => 1,
"PartNumber5" => 1,
"PartNumber6" => 1,
);
$values = array(
"value" => "PartNumber1",
"value2" => "PartNumber2",
"value3" => "PartNumber3",
"value4" => "PartNumber4",
"value5" => "PartNumber5",
"value6" => "PartNumber6",
"value7" => "PartNumber7");
$multipler = 1;
foreach($values as $key => $item){
if(isset($exampleArraY[$item])){
echo $exampleArraY[$item] += $multipler;
}else {
$exampleArraY[$item] = $multipler;
}
}
Output:
array(7) {
["PartNumber1"]=>int(2)
["PartNumber2"]=>int(2)
["PartNumber3"]=>int(2)
["PartNumber4"]=>int(2)
["PartNumber5"]=>int(2)
["PartNumber6"]=>int(2)
["PartNumber7"]=>int(1)
}

Related

Loop an array and retain only elements that relate to a specific key with a qualifying value

I have this array :
(
[id] => block_5df755210d30a
[name] => acf/floorplans
[data] => Array
(
[floorplans_0_valid_for_export] => 0
[floorplans_0_title] => title 1
[floorplans_0_house_area] => 40m²
[floorplans_0_bedrooms] => 1
[floorplans_1_valid_for_export] => 1
[floorplans_1_title] => title xx
[floorplans_1_house_area] => 90m²
[floorplans_1_bedrooms] => 2
[floorplans_2_valid_for_export] => 1
[floorplans_2_title] => title 2
[floorplans_2_house_area] => 50m²
[floorplans_2_bedrooms] => 1
[floorplans] => 3
)
)
As we can see in the data, we have fields (floorplans_X_valid_for_export).
What I want to do is to get the data only when this field equal to 1.
So from the given example, I want to keep only these fields:
[floorplans_1_valid_for_export] => 1
[floorplans_1_title] => title xx
[floorplans_1_house_area] => 90m²
[floorplans_1_bedrooms] => 2
[floorplans_2_valid_for_export] => 1
[floorplans_2_title] => title 2
[floorplans_2_house_area] => 50m²
[floorplans_2_bedrooms] => 1
This is an odd schema, but it can be done by iterating through the array and searching for keys where "valid_for_export" equals 1, and then using another array of field "stubs" to get the associated items by a unique identifier of X in floorplans_X_valid_for_export
$array = [
'floorplans_0_valid_for_export' => 0,
'floorplans_0_title' => 'title 1',
'floorplans_0_house_area' => '40m²',
'floorplans_0_bedrooms' => 1,
'floorplans_1_valid_for_export' => 1,
'floorplans_1_title' => 'title xx',
'floorplans_1_house_area' => '90m²',
'floorplans_1_bedrooms' => '2',
'floorplans_2_valid_for_export' => 1,
'floorplans_2_title' => 'title 2',
'floorplans_2_house_area' => '50m²',
'floorplans_2_bedrooms' => 1,
'floorplans' => 3
];
$stubs = [
'floorplans_%s_valid_for_export',
'floorplans_%s_title',
'floorplans_%s_house_area',
'floorplans_%s_bedrooms'
];
$newArr = [];
foreach ($array as $key => $value) {
if (strpos($key, 'valid_for_export') && $array[$key] == 1) {
$intVal = filter_var($key, FILTER_SANITIZE_NUMBER_INT);
foreach ($stubs as $stub) {
$search = sprintf($stub, $intVal);
if (isset($array[$search])) {
$newArr[$search] = $array[$search];
} else {
// key can't be found, generate one with null
$newArr[$search] = null;
}
}
}
}
echo '<pre>';
print_r($newArr);
Working: http://sandbox.onlinephpfunctions.com/code/23a225e3cefa2dc9cc97f53f1cbae0ea291672c0
Use a parent loop to check that the number-specific valid_for_export value is non-empty -- since it is either 0 or non-zero.
If so, then just push all of the associated elements into the result array.
Some reasons that this answer is superior to the #Alex's answer are:
Alex's parent loop makes 13 iterations (and the same number of strpos() calls); mine makes just 3 (and only 3 calls of empty()).
$array[$key] is more simply written as $value.
Sanitizing the $key to extract the index/counter is more overhead than necessary as demonstrated in my answer.
Code (Demo)
$array = [
'floorplans_0_valid_for_export' => 0,
'floorplans_0_title' => 'title 1',
'floorplans_0_house_area' => '40m²',
'floorplans_0_bedrooms' => 1,
'floorplans_1_valid_for_export' => 1,
'floorplans_1_title' => 'title xx',
'floorplans_1_house_area' => '90m²',
'floorplans_1_bedrooms' => '2',
'floorplans_2_valid_for_export' => 1,
'floorplans_2_title' => 'title 2',
'floorplans_2_house_area' => '50m²',
'floorplans_2_bedrooms' => 1,
'floorplans' => 3
];
$labels = ['valid_for_export', 'title', 'house_area', 'bedrooms'];
$result = [];
for ($i = 0; $i < $array['floorplans']; ++$i) {
if (!empty($array['floorplans_' . $i . '_valid_for_export'])) {
foreach ($labels as $label) {
$key = sprintf('floorplans_%s_%s', $i, $label);
$result[$key] = $array[$key];
}
}
}
var_export($result);
Output:
array (
'floorplans_1_valid_for_export' => 1,
'floorplans_1_title' => 'title xx',
'floorplans_1_house_area' => '90m²',
'floorplans_1_bedrooms' => '2',
'floorplans_2_valid_for_export' => 1,
'floorplans_2_title' => 'title 2',
'floorplans_2_house_area' => '50m²',
'floorplans_2_bedrooms' => 1,
)
With that constructed data it might be hard (not impossble tho), hovewer i would suggest to change it to multidimensional arrays so you have something like:
[floorplans][0][valid_for_export] => 0
[floorplans][0][title] => title 1
[floorplans][0][house_area] => 40m²
[floorplans][0][bedrooms] => 1
[floorplans][1][valid_for_export] => 1
[floorplans][1][title] => title xx
[floorplans][1][house_area] => 90m²
Rought sollution
It is not the best approach, but it should work if you dont need anything fancy, and know that structure of data wont change in future
$keys = [];
$for($i=0;$i<$array['floorplans'];++$i) {
if(isset($array['floorplans_'.$i.'_valid_for_export']) && $array['floorplans_'.$i.'_valid_for_export']===1) {
$keys[] = $i;
}
}
print_r($keys);

PHP – Group output with same ID from within foreach loop

I have a user upload a .csv file from the backend of Wordpress through a custom file upload field (Advanced custom fields). I then call this field to retrieve the data from that file to create an array of said data:
$upload_cq = get_field('report_current_quarter');
$report_cq = array();
if(($handle_cq = fopen($upload_cq, "r")) !== FALSE)
{
while(($data_cq = fgetcsv($handle_cq, 1000, ",")) !== FALSE)
{
$report_cq[] = $data_cq;
}
$results_cq = array_slice($report_cq, 3); // remove unwanted row
fclose($handle_cq);
}
Once I create the array, I then create another array with a key and associate value, and ensure that the "team_id" column is present & not empty, as so (there is a teamName function which I won't get into):
foreach($results_cq as $results)
{
$team_id = $results[6];
if(!empty($team_id))
{
$team_totals_cq[] = array(
'id' => $team_id,
'team' => teamName($team_id),
'total_volume' => $results[41],
'total_closed' => $results[24],
'listings_closed' => $results[22],
'buyers_closed' => $results[23],
'total_agc' => $results[29],
'rental_agc' => $results[30],
);
}
}
echo '<pre>'; print_r($team_totals_cq); echo '</pre>';
When printing the array, I get the following. My question now is; How do I group results with the same team "id" and add up their results (results = total_volume, total_closed, listings_closed, buyers_closed, total_agc, and rental_agc):
Array
(
...
[6] => Array
(
[id] => 0011
[team] => Williamson Team
[total_volume] => $990,000
[total_closed] => 4
[listings_closed] => $0.00
[buyers_closed] => 1
[total_agc] => $20,812.50
[rental_agc] => $23,812.50
)
...
[9] => Array
(
[id] => 0011
[team] => Williamson Team
[total_volume] => $415,000
[total_closed] => 2
[listings_closed] => $0.00
[buyers_closed] => 0
[total_agc] => $12,450.00
[rental_agc] => $12,450.00
)
...
)
I have tried everything within my abilities, and nothing has worked.
One method is to use team_id as keys in $team_totals_cq then simply add up the values as you go through the loop.
(Note: The preg_replace function strips anything that aren't numbers or .)
$team_totals_cq = [];
foreach ($results_cq as $results) {
$team_id = $results[6];
if (!empty($team_id)) {
if (!isset($team_totals_cq[$team_id])) {
$team_totals_cq[$team_id] = [
'id' => $team_id,
'team' => teamName($team_id),
'total_volume' => preg_replace("/[^0-9\.]/", '', $results[41]),
'total_closed' => $results[24],
'listings_closed' => preg_replace("/[^0-9\.]/", '', $results[22]),
'buyers_closed' => $results[23],
'total_agc' => preg_replace("/[^0-9\.]/", '', $results[29]),
'rental_agc' => preg_replace("/[^0-9\.]/", '', $results[30])
];
} else {
$team_totals_cq[$team_id]['total_volume'] += preg_replace("/[^0-9\.]/", '', $results[41]);
$team_totals_cq[$team_id]['total_closed'] += $results[24];
$team_totals_cq[$team_id]['listings_closed'] += preg_replace("/[^0-9\.]/", '', $results[22]);
$team_totals_cq[$team_id]['buyers_closed'] += $result[23];
$team_totals_cq[$team_id]['total_agc'] += preg_replace("/[^0-9\.]/", '', $results[29]);
$team_totals_cq[$team_id]['rental_agc'] += preg_replace("/[^0-9\.]/", '', $results[30]);
}
}
}

Multidimensional Array delete duplicated key values with condition

I have an Array Like this:
$ratesData = [
1 => [
'id' => 1,
'amount' => 2
],
0 => [
'id' => 1,
'amount' => 1
],
2 => [
'id' => 1,
'amount' => 3
],
3 => [
'id' => 2,
'amount' => 2
]
];
I want to keep the duplicated id arrays with cheapest amount, the result will be like this:
[
0 => [
'id' => 1,
'amount' => 1
],
1 => [
'id' => 2,
'amount' => 2
]
]
I have a code that works with this problem, but I'm searching an elegant way to accomplish this without all this loops:
foreach($ratesData as $firstLoopKey => $firstLoopValue) {
foreach($ratesData as $secondLoopKey => $secondLoopValue) {
if($firstLoopValue['id'] === $secondLoopValue['id'] && $firstLoopKey != $secondLoopKey ) {
if ($ratesData[$secondLoopKey]['total_amount'] > $ratesData[$firstLoopKey]['total_amount']) {
$deleteElements[] = $secondLoopKey;
}
}
}
}
if (isset($deleteElements)) {
foreach ($deleteElements as $element) {
unset($ratesData[$element]);
}
}
$ratesData = array_values($ratesData);
return $ratesData;
You can sort by amount descending and then extract the array indexing by id which will eliminate the duplicates with the lowest amount overwriting the higher:
array_multisort(array_column($ratesData, 'amount'), SORT_DESC, $ratesData);
$ratesData = array_column($ratesData, null, 'id');
Yields:
Array
(
[1] => Array
(
[id] => 1
[amount] => 1
)
[2] => Array
(
[id] => 2
[amount] => 2
)
)
I always like having the key the same as a unique id to make array access/sorting easier, but you can re-index if needed:
$ratesData = array_values($ratesData);
Some simple solution:
// your source array
$ratesData = [];
// result array
$filtered = [];
foreach ($ratesData as $v) {
$id = $v['id'];
// if this is `$id`, which is not in `$filtered` yet
// or value of `$filtered[$id]['amount']` is greater then current `$v`
// then replace `$filtered[$id]` with current `$v`
if (!isset($filtered[$id]) || $filtered[$id]['amount'] > $v['amount']) {
$filtered[$id] = $v;
}
}
echo'<pre>',print_r(array_values($filtered)),'</pre>';
Another good solution
$uniqueRates = [];
foreach ($ratesData as $rateData) {
$key = $rateData['id'];
if (!\array_key_exists($key, $uniqueRates) ||
$rateData['total_amount'] < $uniqueRates[$key]['total_amount']
) {
$uniqueRates[$key] = $rateData;
}
}
return array_values($uniqueRates);

How many times an element shows in a multidimensional array

I need to know how many times a "phase" shows up, and if it's completed or not.
The final objective is to show:
Phase 1: 50% completed
Phase 2: 0% completed
Tasks:
Array
(
[0] => Array
(
[phase] => 1
[tasks_status] => completed
)
[1] => Array
(
[phase] => 1
[tasks_status] => pending
)
[2] => Array
(
[phase] => 2
[tasks_status] => pending
)
)
Phases:
Array
(
[0] => Array
(
[title] => Briefing e Planejamento
[id] => 1
[created] => 1437436800
)
[1] => Array
(
[title] => Rabiscos e Design
[id] => 2
[created] => 1438128000
)
)
edit
So, with the help of you guys who answered, I've managed to do it! Here's the result:
/** Define wich tasks has been completed **/
foreach ($tasks as $task) {
if ($task['status'] == "completed") {
foreach ($fases as &$fase) {
if ($fase['id'] == $task['fase_id']) {
$fase['numero_total_fases']++;
$fase['completed']++;
}
}
} elseif ($task['status'] == "pending") {
foreach ($fases as &$fase) {
if ($fase['id'] == $task['fase_id']) {
$fase['numero_total_fases']++;
$fase['pending']++;
}
}
} elseif ($task['status'] == "behind schedule") {
foreach ($fases as &$fase) {
if ($fase['id'] == $task['fase_id']) {
$fase['numero_total_fases']++;
$fase['behind schedule']++;
}
}
}
unset($fase);
}
/** Define progress percentage **/
foreach ($fases as &$fase) {
$fase['progresso'] = round(($fase['completed'] / ($fase['numero_total_fases'])) * 100);
}
/** Print phases progress **/
$f = 1;
foreach ($fases as $fase) {
echo 'Fase '.$f.' - '.$fase['title'].' = '.$fase['progresso'].'% completed';
}
A little slow to the draw, but since I already wrote it, here's my answer too. It's always helpful to see that most programming tasks can be done several ways:
<?php
$tasks = array(
array(
'phase' => 1,
'tasks_status' => 'completed'
),
array(
'phase' => 1,
'tasks_status' => 'pending'
),
array(
'phase' => 2,
'tasks_status' => 'pending'
)
);
//$phases = array();
$phases = array(
1=>array(
'title'=>'Briefing e Planejamento',
'id'=>1,
'created'=>1437436800
),
2=>array(
'title'=>'Rabiscos e Design',
'id'=>2,
'created'=>1438128000
)
);
foreach($tasks as $key=>$task){
if(isset($phases[$task['phase']])){
$thisPhase = $phases[$task['phase']];
}
else{
$thisPhase = array(
'completed' => 0,
'pending' => 0
);
}
$thisPhase[$task['tasks_status']]++;
$phases[$task['phase']] = $thisPhase;
}
foreach($phases as $name=>$phase){
echo $phase['title'].": ".round(($phase['completed'] / ($phase['completed'] + $phase['pending'])) * 100)."% completed <br>";
}
?>
I know you've already finished, but regarding the phases array - you should have put that in the original question if you wanted it worked into the answer. My suggestion, however, would be to use the ID of the phase as the index name in your phases array. The solution I posted will work with that too - and you can then use $phase in the final foreach loop to show the title or created time.
Is this what you are after?
I assume you want to calculate the percentage based on your original array.
<?php
$tasks = array(
array(
'phase' => 1,
'tasks_status' => 'completed'
),
array(
'phase' => 1,
'tasks_status' => 'pending'
),
array(
'phase' => 2,
'tasks_status' => 'pending'
),
);
$phases_arr = array();
foreach($tasks as $task) {
if(!array_key_exists($task['phase'], $phases_arr)) {
$phases_arr[$task['phase']] = array();
}
$phases_arr[$task['phase']][] = $task;
}
$phases = array();
foreach($phases_arr as $phase_num => $phase) {
$p = array(
'phase' => $phase_num,
'total' => count($phase),
'complete' => 0,
'percent' => 0
);
foreach($phase as $task) {
if($task['complete']) $p['complete']++;
}
$p['percent'] = ($p['complete'] / $p['total']) * 100;
$phases[$phase_num] = $p;
}
foreach($phases as $phase) {
echo "<p>Phase {$phase['phase']}: {$phase['percent']}% completed</p>";
}
Your inputs,
$tasks = array( array('phase' => 1, 'tasks_status' => 'completed'),
array('phase' => 1, 'tasks_status' => 'pending'),
array('phase' => 2, 'tasks_status' => 'pending'),
);
Consider this,
$phase = array();
foreach ($tasks as $key => $value)
{
$phase[$value['phase']][] = $value['tasks_status'] == 'completed' ? 50 : 0 ;
}
function get_phase_percentage($i)
{
global $phase;
if(isset($phase[$i]) && is_array($phase[$i]))
return array_sum($phase[$i]);
return 0;
}
Use it like,
Phase 1: <?php echo get_phase_percentage(1)?>% completed
Phase 2: <?php echo get_phase_percentage(2)?>% completed

How to check if a value exists in a Multidimensional array

I have an Multidimensional array that takes a similar form to this array bellow.
$shop = array( array( Title => "rose",
Price => 1.25,
Number => 15
),
array( Title => "daisy",
Price => 0.75,
Number => 25,
),
array( Title => "orchid",
Price => 1.15,
Number => 7
)
);
I would like to see if a value I'm looking for is in the array, and if so, return the position of the element in the array.
Here's a function off the PHP Manual and in the comment section.. Works like a charm.
<?php
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
Found this function in the PHP docs: http://www.php.net/array_search
A more naive approach than the one showed by Zander, you can hold a reference to the outer key and inner key in a foreach loop and store them.
$outer = "";
$inner = "";
foreach($shop as $outer_key => $inner_array){
foreach($inner_array as $inner_key => $value) {
if($value == "rose") {
$outer = $outer_key;
$inner = $inner_key;
break 2;
}
}
}
if(!empty($outer)) echo $shop[$outer][$inner];
else echo "value not found";
You can use array_map with in_array and return the keys you want
$search = 1.25;
print_r(
array_filter(array_map(function($a){
if (in_array($search, $a)){
return $a;
}
}, $shop))
);
Will print:
Array
(
[0] => Array
(
[Title] => rose
[Price] => 1.25
[Number] => 15
)
)
php >= 5.5
$shop = array( array( 'Title' => "rose",
'Price' => 1.25,
'Number' => 15
),
array( 'Title' => "daisy",
'Price' => 0.75,
'Number' => 25,
),
array( 'Title' => "orchid",
'Price' => 1.15,
'Number' => 7
)
);
$titles = array_column($shop,'Title');
if(!empty($titles['rose']) && $titles['rose'] == 'YOUR_SEARCH_VALUE'){
//do the stuff
}

Categories