calcultion based on items minus stock value php - php

I have a calcultion based on items minus stock value (with some community help). If it hits zero then the next row will be touched.
$items = 45;
$stockRows = [40, 50, 60];
$newStock = function ($items, $stock) {
foreach ($stock as &$item) {
$delta = $item - $items;
$item = $delta > 0 ? $delta : 0;
$items = $delta < 0 ? abs($delta) : 0;
}
return $stock;
};
print_r($newStock($items, $stockRows));
Output
Array
(
[0] => 0
[1] => 45
[2] => 60
)
Now I want to add a row identifier so that I can update the database rows afterwards in a foreach and set the correct stock amount
$stockRows =
array(
array(
'id' => 1,
'amount' => 30
),
array(
'id' => 2,
'amount' => 40
),
array(
'id' => 3,
'amount' => 50
)
);
I cant get this to work. And if I get a output the first array result returns id 0.

Fixed it myself
$items = 45;
$ids = [1, 2, 3];
$stockRows = [40, 50, 60];
$newStock = function ($afschrijving, $stock, $ids) {
$i = 0;
foreach ($stock as &$item) {
$delta = $item - $afschrijving;
$item = array($id[$i++], $delta > 0 ? $delta : 0);
$afschrijving = $delta < 0 ? abs($delta) : 0;
}
return $stock;
};
print_r($newStock($items, $stockRows, $ids));

Related

PHP - add values to already existing array

I have a already defined array, containing values just like the one below:
$arr = ['a','b','c'];
How could one add the following using PHP?
$arr = [
'a' => 10,
'b' => 5,
'c' => 21
]
I have tried:
$arr['a'] = 10 but it throws the error: Undefined index: a
I am surely that I do a stupid mistake.. could someone open my eyes?
Full code below:
$finishes = []; //define array to hold finish types
foreach ($projectstages as $stage) {
if ($stage->finish_type) {
if(!in_array($stage->finish_type, $finishes)){
array_push($finishes, $stage->finish_type);
}
}
}
foreach ($projectunits as $unit) {
$data[$i] = [
'id' => $unit->id,
'project_name' => $unit->project_name,
'block_title' => $unit->block_title,
'unit' => $unit->unit,
'core' => $unit->core,
'floor' => $unit->floor,
'unit_type' => $unit->unit_type,
'tenure_type' => $unit->tenure_type,
'floors' => $unit->unit_floors,
'weelchair' => $unit->weelchair,
'dual_aspect' => $unit->dual_aspect
];
$st = array();
$bs = '';
foreach ($projectstages as $stage) {
$projectmeasure = ProjectMeasure::select('measure')
->where('project_id',$this->projectId)
->where('build_stage_id', $stage->id)
->where('unit_id', $unit->id)
->where('block_id', $unit->block_id)
->where('build_stage_type_id', $stage->build_stage_type_id)
->first();
$st += [
'BST-'.$stage->build_stage_type_id => ($projectmeasure ? $projectmeasure->measure : '0')
];
if (($stage->is_square_meter == 0) && ($stage->is_draft == 0)) {
$height = ($stage->height_override == 0 ? $unit->gross_floor_height : $stage->height_override); //08.14.20: override default height if build stage type has it's own custom height
$st += [
'BST-sqm-'.$stage->build_stage_type_id => ($projectmeasure ? $projectmeasure->measure * $height: '0')
];
if ($stage->finish_type) {
$finishes[$stage->finish_type] += ($projectmeasure ? $projectmeasure->measure * $height: '0') * ($stage->both_side ? 2 : 1); //error is thrown at this line
}
} else {
if ($stage->finish_type) {
$finishes[$stage->finish_type] += ($projectmeasure ? $projectmeasure->measure : '0');
}
}
}
$data[$i] = array_merge($data[$i], $st);
$data[$i] = array_merge($data[$i], $finishes[$stage->finish_type]);
$i++;
}
The above code is used as is and the array $finishes is the one from the first example, called $arr
You're using += in your real code instead of =. That tries to do maths to add to an existing value, whereas = can just assign a new index with that value if it doesn't exist.
+= can't do maths to add a number to nothing. You need to check first if the index exists yet. If it doesn't exist, then assign it with an initial value. If it already exists with a value, then you can add the new value to the existing value.
If you want to convert the array of strings to a collection of keys (elements) and values (integers), you can try the following:
$arr = ['a','b','c'];
$newVals = [10, 5, 21];
function convertArr($arr, $newVals){
if(count($arr) == count($newVals)){
$len = count($arr);
for($i = 0; $i < $len; $i++){
$temp = $arr[$i];
$arr[$temp] = $newVals[$i];
unset($arr[$i]);
}
}
return $arr;
}
print_r(convertArr($arr, $newVals));
Output:
Array ( [a] => 10 [b] => 5 [c] => 21 )

Compare two multidimensional arrays in PHP to sum datas

I've two arrays:
Array A:
$rates = array(
'apple' = array(
'red' => 1.19,
'green' => 0.99,
'yellow' => 0.89
)
);
Array B:
$cart = array(
'apple' = array(
'0' => red,
'1' => green
)
);
The array B is the cart one and I need to get rates from Array A.
So:
Apple > red > 1.19
Apple > green > 0.99
Total should be 2.18.
This is what I tried:
foreach($cart as $key => $arr){
if(!in_array($key[$arr], $rates)){
$total += $rates[$key];
}
}
But it doesn't work.
What I'm missing please ?
Thanks a lot for any help.
You have a couple of problems. Firstly, you should be checking whether the product type from $cart exists as a key in $rates i.e.
if(!in_array($key[$arr], $rates)){
should be:
if (isset($rates[$key])) {
Secondly, once you have determined that the key does exist in $rates you then need to iterate over each of the values in $arr to get their price from $rates (using the null coalescing operator to avoid problems with values not being in the rates array):
$total = 0;
foreach ($cart as $key => $arr) {
if (isset($rates[$key])) {
foreach ($arr as $value) {
$total += $rates[$key][$value] ?? 0;
}
}
}
echo $total;
Output:
2.18
Demo on 3v4l.org
<?php
$rates = array(
'apple' => array(
'red' => 1.19,
'green' => 0.99,
'yellow' => 0.89
)
);
$cart = array(
'apple' => array(
'0' => 'red',
'1' => 'green'
)
);
$total = 0;
foreach($cart as $type => $items) {
if(array_key_exists($type, $rates)) {
foreach($items as $item) {
if(array_key_exists($item, $rates[$type])) {
$total += $rates[$type][$item];
}
}
}
}
echo $total;
?>

Pointer of Array conditional sum qty

I have a question about how to make an iteration. I want to place a total row after each item in the array if the next element in the array matches a specific condition. Spesific conditions have logic like this
the data like this
if i request a qty for example = 60 the result i hope like this
you can see
data[2] = 01/03/2020 just took 10 out of 40
$iter = new \ArrayIterator($values);
$sum = 0;
foreach($values as $key => $value) {
$nextValue = $iter->current();
$iter->next();
$nextKey = $iter->key();
if(condition) {
$sum += $value;
}
}
dd($iter);
how to make this logic work on php language/ laravel?
Following logic might help you on your way:
<?php
$stock = [
'01/01/2020' => 20,
'01/02/2020' => 30,
'01/03/2020' => 40
];
showStatus($stock, 'in stock - before transaction');
$demand = 60;
foreach ($stock as $key => $value) {
if ($value <= $demand) {
$stock[$key] = 0;
$supplied[$key] = $value;
$demand -= $value;
} else {
$stock[$key] -= $demand;
$supplied[$key] = $value - ($value - $demand);
$demand = 0;
}
}
showStatus($supplied, 'supplied');
showStatus($stock, 'in stock - after transaction');
function showStatus($arr = [], $msg = '')
{
echo $msg;
echo '<pre>';
print_r($arr);
echo '</pre>';
}
?>
**Output:**
in stock - before transaction
Array
(
[01/01/2020] => 20
[01/02/2020] => 30
[01/03/2020] => 40
)
supplied
Array
(
[01/01/2020] => 20
[01/02/2020] => 30
[01/03/2020] => 10
)
in stock - after transaction
Array
(
[01/01/2020] => 0
[01/02/2020] => 0
[01/03/2020] => 30
)
Working demo
I'm not sure I've understood you correctly but this might help:
$values = [
'01/01/2020' => 20,
'01/02/2020' => 30,
'01/03/2020' => 40
];
$demand = 60;
$total = array_sum($values);
$decrease = $total - $demand; //(20+30+40) - 60 = 30
$last_key = array_keys($values,end($values))[0]; //Is 01/03/2020 in this case
$values[$last_key] -= $decrease; //Decrease value with 30 calulated above
Would output:
Array
(
[01/01/2020] => 20
[01/02/2020] => 30
[01/03/2020] => 10
)

How to count the number of item in foreach loop based by it's parent?

I have a simple loop to display a list. But I do not know how to count it's parent item. This is my current attempt:
$no = 0;
$ct = 0;
$type = "";
foreach($item as $row_item){
$no = $no + 1;
if($type != $row_item['type']){
$ct = $ct + 1;
}
echo $no." ".$row_item['type']." ".$row_item['item'];
$type = $row_item['type'];
}
My desired output :
1 TYPE_A 3 A1
2 TYPE_A 3 A2
3 TYPE_A 3 A3
4 TYPE_B 2 B1
5 TYPE_B 2 B2
In order to count the total number of each type you'll need to iterate over the entire collection twice. Once to count the totals, and once to display the results for each row. The code below actually does 3 loops, the array_filter method iterates over the entire array, but I like the clean code. :)
http://sandbox.onlinephpfunctions.com/code/962f418715d1518c818732f6e59ba4f28d5a19f3
<?php
$items = array(
array( 'name' => 'A1', 'type' => 'TYPE_A' ),
array( 'name' => 'A2', 'type' => 'TYPE_A' ),
array( 'name' => 'A3', 'type' => 'TYPE_A' ),
array( 'name' => 'B1', 'type' => 'TYPE_B' ),
array( 'name' => 'B2', 'type' => 'TYPE_B' )
);
function is_TYPE_A( $item ) {
return $item['type'] == 'TYPE_A';
}
function is_TYPE_B( $item ) {
return $item['type'] == 'TYPE_B';
}
$TYPE_A_COUNT = count( array_filter( $items, 'is_TYPE_A' ) );
$TYPE_B_COUNT = count( array_filter( $items, 'is_TYPE_B' ) );
function getTypeTotalByItem( $item ) {
global $TYPE_A_COUNT, $TYPE_B_COUNT;
if ( $item['type'] == 'TYPE_A' ) {
return $TYPE_A_COUNT;
}
if ( $item['type'] == 'TYPE_B' ) {
return $TYPE_B_COUNT;
}
}
for ( $i = 0; $i < count( $items ); $i++ ) {
echo ( $i + 1 )." ".$items[$i]['type']." ".getTypeTotalByItem($items[$i])." ".$items[$i]['name']."\n";
}
You can use array_map() and a couple foreach() loops for this if you were so inclined. It should interpret fairly quickly:
# Create a storage array
$counter = [];
# Sort the main array into type
array_map(function($v) use (&$counter){
# Store the subs under the type
$counter[$v['type']][] = $v['item'];
},$items);
# Start counter
$i = 1;
# Loop through each type
foreach($counter as $title => $row){
# Count how many are under this type
$count = count($row);
# Loop the rows in the types arrays
foreach($row as $item) {
# Write increment, type, total count, item
echo $i." ".$title." ".$count." ".$item.'<br />';
$i++;
}
}

Splitting a Associative Array Based off if Condition of Value

I'm combining an array based off a MySQL Query:
$newskus = array();
$newqtys = array();
$sql1 = $db->query("//QUERY//");
while($row = $sql1->fetch_assoc()) {
$newskus[] = $row['SKU'];
$newqtys[] = $row['Quantity'];
}
$newskusandqtys = array_combine($newskus, $newqtys);
This gives me an associative array like so:
Array
(
[Product 1] => -1
[Product 2] => 0
[Product 3] => 3
)
I'm looking to split this array based off the condition of the integer value.
That is, if the value is above 0, it'll put the contents into a variable $newqtysabovezero
Ending with an expected output of
Array
(
[Product 3] => 3
)
And the other way around, if the value is greater than or equal to 0, put this into an array variable $newqtysbelowzero with an expected output of
Array
(
[Product 1] => -1
[Product 2] => 0
)
I'm able to do this with a numerical array, but it of course is not passing the key:
foreach( $newqtys as $item ) {
if ( $item > '0' ) {
$newqtysabovezero[] = $item;
} elseif ( $item <= '0') {
$newqtysbelowzero[] = $item;
}
}
How would I modify this to get my expected output?
Here is one way:
foreach( $newqtys as $key => $item ) {
if ( $item > '0' ) {
$newqtysabovezero[$key] = $item;
} elseif ( $item <= '0') {
$newqtysbelowzero[$key] = $item;
}
}
And here is a method using array_filter():
$in = array(
'Product 1' => -1,
'Product 2' => 0,
'Product 3' => 3
);
function at_and_below($v) {
return $v <= 0;
}
function above($v) {
return $v > 0;
}
$newqtysabovezero = array_filter($in, 'above');
$newqtysbelowzero = array_filter($in, 'at_and_below');
At first, to get all values from the 'Quantity' field as integers you should cast them to integer type:
...
while($row = $sql1->fetch_assoc()) {
$newskus[] = $row['SKU'];
$newqtys[] = (int) $row['Quantity'];
}
$newskusandqtys = array_combine($newskus, $newqtys);
Then, you can easily separate values which are greater than OR equal/less than 0:
foreach (newskusandqtys as $k => $item) {
if ($item > 0) {
$newqtysabovezero[$k] = $item;
} else {
$newqtysbelowzero[$k] = $item;
}
}
You can skip the array_combine part, and just read the values into the final arrays as you fetch them.
while($row = $sql1->fetch_assoc()) {
if ($row['Quantity'] > 0) {
$newqtysabovezero[$row['SKU']] = $row['Quantity'];
} else {
$newqtysbelowzero[$row['SKU']] = $row['Quantity'];
}
}

Categories