Recursive Deduction of array - php

Hi I have this array values
# amount deduction
[0] 50 10
[1] 160 20
[2] 300 20
I want to have a recursive deduction of these arrays until data is zero, and then if the first amount of the array is zero(0) the deduction will add to the next data, until all amount will be zero (0). Sample Calculation below
[0] [1] [2]
50 - 10 160 - 20 300 - 20
40 - 10 140 - 20 280 - 20
30 - 10 120 - 20 260 - 20
20 - 10 100 - 20 240 - 20
10 - 10 80 - 20 220 - 20
0 60 - 30 200 - 20
30 - 30 180 - 20
0 160 - 50
110 - 50
60 - 50
10 - 50
0
I don't know how to do it but this is my code so far.
foreach($data as $det)
{
$_monthly_payment = $det->deduction;
$_beginning_balance = $det->amount;
$i = 0;
do{
$_new_balance = (($i + 1) == 1) ? $_beginning_balance : $_ending_balance;
$_toward_principal = $_monthly_payment;
$_ending_balance = $_new_balance - $_toward_principal;
<tr>
<td><?php echo number_format($_monthly_payment,2); ?></td>
<td>$<?php echo number_format($_new_balance,2); ?> </td>
<td>$<?php echo number_format($_toward_principal,2); ?> </td>
<td>$<?php echo number_format($_ending_balance,2); ?> </td>
</tr>
}
while( $i <= $_ending_balance );
}
Please don't judge me guys, I just need this so badly. Thank you guys.
Updated
Result of my var_dump
object(Illuminate\Support\Collection)#1334 (1) {
["items":protected]=> array(3) {
[0]=> object(stdClass)#1341 (26) {
["id"]=> int(130) ["account_name"]=> string(3) "QWE" ["amount"]=> float(50) ["deduction"]=> float(10) ["updated_at"]=> string(19) "2023-01-09 15:49:59" }
[1]=> object(stdClass)#1345 (26) {
["id"]=> int(131) ["account_name"]=> string(3) "ABC" ["amount"]=> float(160) ["deduction"]=> float(20) ["updated_at"]=> string(19) "2023-01-09 15:49:59" }
[2]=> object(stdClass)#1326 (26) {
["id"]=> int(132) ["account_name"]=> string(3) "XYZ" ["amount"]=> float(300) ["deduction"]=> float(20) ["updated_at"]=> string(19) "2023-01-09 15:49:59" }
}
}

this is the answer big help of #CBroe. This will continue the deduction if the first data of the array is zero(0).
<?php
$data = [
['amount' => 50, 'deduction' => 10],
['amount' => 160, 'deduction' => 20],
['amount' => 300, 'deduction' => 20],
];
$continue = true;
echo '<table>';
while($continue) {
$continue = max(array_column($data, 'amount')) > 0;
echo '<tr>';
for($i=0; $i<count($data); ++$i) {
echo '<td>';
echo !isset($data[$i]['done']) ? max($data[$i]['amount'], 0) : '';
if($data[$i]['amount'] <= 0 && !isset($data[$i]['done'])) {
$data[$i]['done'] = true;
if(isset($data[$i+1])) {
$data[$i+1]['deduction'] += $data[$i]['deduction'];
}
}
echo !isset($data[$i]['done']) ? ' - '.$data[$i]['deduction'] : '';
echo '</td>';
$data[$i]['amount'] -= $data[$i]['deduction'];
}
echo '</tr>';
}
echo '</table>';

Related

Filter array rows if datetime value is within 10 minutes of target time

I do a foreach on an object that I call $file. This object has a property which is the datetime ($file[6]) and another with the name ($file[0]). I need to add the object to an array if the difference between createDate and $file[6] are within 10 minutes of each other.
My desired result structure is:
[
[ $file[0], $file[6] ], // More than 1 results
[ $file[0], $file[6] ],
...
]
As you can see in the code below:
$createDate = $prop['created_date'];
$result = array();
foreach($obj['files'] as $file) {
$fileName = $file[0];
$fileDateTime = $file[6];
$differenceInSeconds = strtotime($fileDateTime) - strtotime($createDate);
$differenceInSeconds = abs($differenceInSeconds);
$convertMinutes = 10 * 60; // 10 minutes
if ($differenceInSeconds < $convertMinutes) {
// Need a array of array that show the name ($file[0]) and datetime ($file[6])
// when the difference between $createDate and $file[6] is less 10 minutes
// (or is between 0 and 600, I guess)
array_push($result, $file); // Here need push array name and date
break;
}
}
echo json_encode($result);
Var_dump in $createDate and $file show this:
$createDate:
DataType: json Message: object(IP_DateTime)#77 (3) {
["date"]=>
string(26) "2022-04-25 03:38:15.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(17) "America/Sao_Paulo"
}
$file:
array(9) {
[0]=>
string(26) "20220407_10_22_30_L100.SVL"
[1]=>
int(2)
[2]=>
string(8) "20220407"
[3]=>
int(4766)
[4]=>
int(307)
[5]=>
int(101366)
[6]=>
string(19) "2022-04-07 13:34:10"
[7]=>
int(0)
[8]=>
int(1)
}
This should work if I understood correctly
$createDate = $prop['created_date'];
$result = array();
$index = 0;
foreach ($obj['files'] as $file) {
$fileName = $file[0];
$fileDateTime = $file[6];
$differenceInSeconds = strtotime($fileDateTime) - strtotime($createDate);
$differenceInSeconds = abs($differenceInSeconds);
$convertMinutes = 600; // 10 minutes
if ($differenceInSeconds < $convertMinutes) {
$result[$index] = array($fileName,$fileDateTime);
$index++;
}
}
echo json_encode($result);
Adding a bit of explanation: I'm using $result[$index] instead of array_push because if you push an array into an array, it would just push in all its items instead of adding the new array as an actual array, which was happening to you.
This task can be directly and efficiently completed by preparing string-comparable datetime values before looping. Because the datetime format is "big-endian", you don't need to perform iterated math/date calculations. You can use simple, clear greater/less than operators to determine qualifying data sets.
Code: (Demo)
$prop['created_date'] = '2022-04-07 13:38:15.000000';
$obj['files'] = [
["20220407_10_22_30_L100.SVL", 2, "20220407", 4766, 307, 101366, "2022-04-07 13:24:10"],
["20220407_10_22_30_L101.SVL", 3, "20220407", 4767, 308, 101367, "2022-04-07 13:29:10"],
["20220407_10_22_30_L102.SVL", 4, "20220407", 4768, 309, 101368, "2022-04-07 13:34:10"],
["20220407_10_22_30_L103.SVL", 5, "20220407", 4769, 310, 101369, "2022-04-07 13:39:10"],
["20220407_10_22_30_L104.SVL", 6, "20220407", 4770, 311, 101370, "2022-04-07 13:44:10"],
["20220407_10_22_30_L105.SVL", 7, "20220407", 4771, 312, 101371, "2022-04-07 13:49:10"],
];
// prepare the date range data only once, before looping
$from = date('Y-m-d H:i:s', strtotime($prop['created_date'] . ' - 10 minutes'));
$to = date('Y-m-d H:i:s', strtotime($prop['created_date'] . ' + 10 minutes'));
$result =[];
foreach ($obj['files'] as $file) {
if ($from <= $file[6] && $file[6] <= $to) {
$result[] = [$file[0], $file[6]];
}
}
var_export($result);
Output:
array (
0 =>
array (
0 => '20220407_10_22_30_L101.SVL',
1 => '2022-04-07 13:29:10',
),
1 =>
array (
0 => '20220407_10_22_30_L102.SVL',
1 => '2022-04-07 13:34:10',
),
2 =>
array (
0 => '20220407_10_22_30_L103.SVL',
1 => '2022-04-07 13:39:10',
),
3 =>
array (
0 => '20220407_10_22_30_L104.SVL',
1 => '2022-04-07 13:44:10',
),
)

Verify length of each string of an array

I want to make a verification that if one of these strings has a length greater than 40 echo "this array contains a string with a length greater than 40". So in this case the index [11] contains a string length that is greater than 40. How can I do that?
array(5) {
[0]=>
string(19) "PEDRO MOACIR LANDIM"
[1]=>
string(19) "ADIR JOAO GASTALDON"
[2]=>
string(18) "ABEL PEDRO MARQUES"
[10]=>
string(28) "ADRIANO CESAR GARCIA JOAQUIM"
[11]=>
string(44) "AUTO VIAÇÃO CATARINENSE LTDA - FLORIANÓPOLIS"
}
foreach ($array as $key => $value) {
if(mb_strlen($value) > 40){
echo "this array contain a string wich lenght is greater than 40: ".$key;
}
}
Since only one of the strings is needed to be detected if it's greater than 40, it's better to break the loop once a number greater than 40 is encountered. This can reduce the number of iterations executed by your for loop if ever the number isn't located at the last index of your array.
foreach ($array as $arr) {
if(mb_strlen($arr) > 40){
echo "this array contain a string wich length is greater than 40";
break;
}
}
You can do this:
<?php
$myStrings = array(
0 => "PEDRO MOACIR LANDIM",
1 => "ADIR JOAO GASTALDON",
2 => "ABEL PEDRO MARQUES",
10 => "ADRIANO CESAR GARCIA JOAQUIM",
11 => "AUTO VIAÇÃO CATARINENSE LTDA - FLORIANÓPOLIS"
);
foreach($myStrings as $key => $string){
//Get length of string
$len = strlen( $string );
if( $len > 40 ){
echo
'this array contain a string wich length is greater than 40. Array key:
' .$key. ' | array string: ' .$string;
break;
}
}
?>

PHP Cant get the count of array child elements

I am trying to get the count and values of stocklevels from the following
Array ( [barcodes] => Array ( [barcode] => 10011010009 ) [basePrice] => 25.00 [customFields] => Array ( ) [description] => CBC-CBCJSW [discontinued] => false [PLU] => CBC Boy's Shirt 20 [priceLevels] => Array ( ) [primaryCategory] => CBC- Boys Shirts [productLineName] => CBC Boy's Shirt 20 [promptPOSOperatorForPrice] => false [sellByWeightOption] => false [stock] => Array ( [stockLevel] => Array ( [0] => Array ( [outletExportCode] => Level1 [stockCount] => 500.000000 ) [1] => Array ( [outletExportCode] => Level2 [stockCount] => 1000.000000 ) ) ) [taxes] => Array ( [taxName] => GST ) )
I have tried the following and i get 1 as the count all the time even if there are 2 levels in the array:
count($ra['stock']['stockLevel']['stockCount']);
count($ra['stock']['stockLevel']);
Also, i am trying to loop through the results to get teh stockcount but it doesnt seem to work:
$stockLevelArr[] = $ra['stock'];
$totalStock = 0;
for($i=0;$i<count($stockLevelArr);$i++){
echo $ra['productLineName'] . ' - Stock outside IF: ' . (int) $stockLevelArr[$i]['stockLevel']['stockCount'];
echo '<br>';
if (isset($stockLevelArr[$i]['stockLevel']['stockCount'])) {
$totalStock = $totalStock + $stockLevelArr[$i]['stockLevel']['stockCount'];
}
}
echo 'Stock count: ' . $totalStock;
echo '<br>';
var dump
array(13) { ["barcodes"]=> array(1) { ["barcode"]=> string(11) "10011010009" } ["basePrice"]=> string(5) "25.00" ["customFields"]=> array(0) { } ["description"]=> string(10) "CBC-CBCJSW" ["discontinued"]=> string(5) "false" ["PLU"]=> string(18) "CBC Boy's Shirt 20" ["priceLevels"]=> array(0) { } ["primaryCategory"]=> string(16) "CBC- Boys Shirts" ["productLineName"]=> string(18) "CBC Boy's Shirt 20" ["promptPOSOperatorForPrice"]=> string(5) "false" ["sellByWeightOption"]=> string(5) "false" ["stock"]=> array(1) { ["stockLevel"]=> array(2) { [0]=> array(2) { ["outletExportCode"]=> string(13) "Tara Uniforms" ["stockCount"]=> string(10) "500.000000" } [1]=> array(2) { ["outletExportCode"]=> string(3) "CBC" ["stockCount"]=> string(11) "1000.000000" } } } ["taxes"]=> array(1) { ["taxName"]=> string(3) "GST" } }
I will appreciate any help.
UPDATE: Following worked. Thanks everyone for your replies and assistance.
$totalStock = 0;
$times_found = 0;
$stock = $ra['stock'];
foreach($stock['stockLevel'] as $stock_level) {
if(isset($stock_level['stockCount'])) {
$times_found++;
$totalStock = $totalStock + $stock_level['stockCount'];
}
}
I'm assuming you mean you want to know how many times stockCount is within the array? If so, I'd use array to loop through each index of the array and increment a variable each time it's found. For example:
$times_found = 0;
foreach($ra['stock'] as $stock) {
foreach($stock['stockLevel'] as $stock_level) {
if(isset($stock_level['stockCount'])) {
$times_found++;
}
}
}
You should count recursive to get all the keys in the count:
count($ra, COUNT_RECURSIVE);
See also the php manual https://www.php.net/manual/en/function.count.php
And I think you should change your for loop to this:
<?php
$totalStock = 0;
foreach ($ra['stock'] as $stock) {
echo $ra['productLineName'] . ' - Stock outside IF: ' . (int) $stock['stockLevel']['stockCount'];
echo '<br>';
if (isset($stock['stockLevel']['stockCount'])) {
$totalStock = $totalStock + $stock['stockLevel']['stockCount'];
}
}
echo 'Stock count: ' . $totalStock;
echo '<br>';
Instead of the for loop, dont know why you did use that, you better use the foreach in this example.

PHP creating an multidimensional array from posted hours and minutes for each day

I am trying to achieve the following array format from posted attributes on a form:
$schedule = array(
'Mon'=>array('09:00','17:00','16:00','15:00','14:00','13:00','12:00','11:00','10:00'),
'Tue'=>array('17:00','16:00','15:00','14:00','13:00','12:00','11:00','10:00','09:00'),
'Wed'=>array('17:00','16:00','15:00','14:00','13:00','12:00','11:00','10:00','09:00'),
'Thu'=>array('12:00','11:00','10:00','09:00'),
'Fri'=>array('09:00'),
'Sat'=>array('17:00','16:00','15:00','14:00','13:00','12:30','11:00','10:00','09:30'),
'Sun'=>array('17:00','16:00','15:00','14:00','13:00','12:00','11:00','10:00','09:00')
);
In my form I have separate Hours and Minutes select boxes to choose the hours and minutes for each day (display wise, they are in tabs).
<div class="controls">
<select name="schedule_hour[0][]" class="input-mini">
<option value="-1">--</option>
<option value="00">00</option>
<option value="01">01</option>
<option value="02">02</option>
etc.
</select>
<select name="schedule_minute[0][]" class="input-mini">
<option value="-1">--</option>
<option selected="selected" value="00">00</option>
<option value="01">01</option>
<option value="02">02</option>
etc.
</select>
</div>
Where schedule_minute[0][] would be an array of minutes for monday. Tuesday would be schedule_minute[2][] and so on.
As far as I have got I have this:
for($i = 0; $i < 7; $i++) {
print_r(array(date('D', strtotime("Monday +{$i} days")), array_combine($_POST['schedule_hour'][$i], $_POST['schedule_minute'][$i])));
}
Which gets me close, but still not right, the above returns:
Array
(
[0] => Mon
[1] => Array
(
[09] => 00
[10] => 00
[11] => 00
[12] => 00
[13] => 00
[14] => 00
[15] => 00
[16] => 00
[17] => 00
)
)
The idea is to then serialise the array and save it to a database. But I need the structure in the correct format first.
Please help.
Here is the code with all necessary checks:
$result = array();
for ($i = 0; $i < 7; ++$i) {
if (isset($_POST['schedule_hour'][$i], $_POST['schedule_minute'][$i])
&& is_array($_POST['schedule_hour'][$i])
&& is_array($_POST['schedule_minute'][$i])
&& ($count = count($_POST['schedule_hour'][$i]))
&& ($count === count($_POST['schedule_minute'][$i]))
) {
$add = array();
foreach ($_POST['schedule_hour'][$i] as $k => $hour) {
if (!isset($_POST['schedule_minute'][$i][$k])) {
continue;
}
$hour = (int) $hour;
$minute = (int) $_POST['schedule_minute'][$i][$k];
if (($hour >= 0) && ($hour <= 23)
&& ($minute >=0) && ($minute <= 59)
) {
$add[] = str_pad($hour, 2, '0', STR_PAD_LEFT) . ':' . str_pad($minute, 2, '0', STR_PAD_LEFT);
}
}
if ($add) {
$result[date('D', strtotime("Monday +{$i} days"))] = $add;
}
}
}
Assuming we have following values:
$_POST['schedule_hour'] = array(
0 => array(2, 10, 12, 13, 26),
3 => array(11, 12, ),
);
$_POST['schedule_minute'] = array(
0 => array(5, 15, 25, 35, 61),
3 => array(40, 50, ),
);
$result will store:
array(2) {
["Mon"]=>
array(4) {
[0]=>
string(5) "02:05"
[1]=>
string(5) "10:15"
[2]=>
string(5) "12:25"
[3]=>
string(5) "13:35"
}
["Thu"]=>
array(2) {
[0]=>
string(5) "11:40"
[1]=>
string(5) "12:50"
}
}
Instead of array_combine you will need to do something like this...
$times = array();
for($x = 0; $x< count($_POST['schedule_hour'][$i]); $x++){
$times[] = $_POST['schedule_hour'][$i][$x].":".
$_POST['schedule_minute'][$i][$x];
}
So your code should look something like this:
for($i = 0; $i < 7; $i++) {
$times = array();
for($x = 0; $x< count($_POST['schedule_hour'][$i]); $x++){
$times[] = $_POST['schedule_hour'][$i][$x].":".
$_POST['schedule_minute'][$i][$x];
}
print_r(array(date('D', strtotime("Monday +{$i} days"))=>$times);
}

how to do the calculation in an array

I have an array :
Array
(
[0] => Array
(
[batch_id] => 1
[seq_id] => 1
[q_id] => 2046
[a1] => 0
[a2] => 1
[a3] => 2
[a4] => 3
[a5] => 4
)
)
I need to minus the value of a1-a5 by 1
desire result(e.g. a1):
array(4) {
["w_id"]=>
string(5) "99911"
["q_id"]=>
string(4) "2046"
["c_id"]=>
string(6) "a1"
["rank"]=>
int(1) "-1"
}
My code is as follow:
$result = mysql_query("Select * from table_1");
while($cr = mysql_fetch_array($result)){
$rr_id = $cr['batch_id'].$cr['seq_id'];
$rid = '999'.$rr_id;
$q_id = $cr['q_id'];
foreach ($cr as $k => $v){
if(preg_match('{^a\d+$}',$k)){
$new_insert[] = array(
'w_id'=>$rid,
'q_id' =>$q_id,
'c_id' =>$k,
'rank'=>$v-1
);
}
}
However, the result of rank becomes
array(4) {
["w_id"]=>
string(5) "99911"
["q_id"]=>
string(4) "2046"
["c_id"]=>
string(6) "a1"
["rank"]=>
int(0)
}
Cannot show the value of rank
Any problem with my code??Can someone answer my question thank you very much
You can use :
$data = array_map(function ($v) {
foreach($v as $k => &$x) {
if (preg_match('{^a\d+$}', $k)) {
$x = $x - 1;
}
}
return $v;
}, $data);
print_r($data);
Live Demo
preg_match('{^Item \d+$}',$k)
You've got wrong pattern inside preg_match (keys you are looking for are 'a1','a2'... not 'item 1', 'item 2'...), just use this one:
preg_match('{^a\d+$}',$k)
Just use loop and pre decrementation
foreach($cr as $k=>&$v)
{
--$v['a1'];--$v['a2'];--$v['a3'];--$v['a4'];--$v['a5'];
}
print_r($cr);
I use $cr as your array.
$cr[] = array("batch_id"=>1, "seq_id"=>1, "q_id"=>'2046', "a1"=>1,"a2"=>1,"a3"=>1,"a4"=>1,"a5"=>1);
foreach($cr as $k=>&$v){
$v['a1'] = $v['a1'] - 1;
$v['a2'] = $v['a2'] - 1;
$v['a3'] = $v['a3'] - 1;
$v['a4'] = $v['a4'] - 1;
$v['a5'] = $v['a5'] - 1;
}
print_r($cr);

Categories