Unify quantities in one item - php

I have two arrays which have items and quantities and they are asociated by the index of the arrays. Example:
Items=XL,M,XL,S
Quantities=5,2,4,7
What I want to achieve is to remove the repetitive items and sum their quantities:
Items=XL,M,S
Quantities=9,2,7
$uniqueTallesTotalesC = array_unique($tallesTotalesC);
for($i=0;$i<Count($uniqueTallesTotalesC);$i++){
for($e=0;$e<Count($cantidadesTotalesC);$e++){
if($uniqueTallesTotalesC[$i]==$tallesTotalesC[$e] && $e > $i){
$cantidadesTotalesC[$i] = $cantidadesTotalesC[$i] + $cantidadesTotalesC[$e];
} else{
}
}
}

You can just blindly zip-merge them together with summation:
$items = explode(',', 'XL,M,XL,S');
$quantities = explode(',', '5,2,4,7');
if(count($items) !== count($quantities)){
throw new RuntimeException('Count mismatch');
}
$final = [];
for($i = 0; $i < count($items); $i++) {
if(!isset($final[$items[$i]])){
$final[$items[$i]] = 0;
}
$final[$items[$i]] += $quantities[$i];
}
var_dump($final);
Outputs:
array(3) {
["XL"]=>
int(9)
["M"]=>
int(2)
["S"]=>
int(7)
}
Demo: https://3v4l.org/6A5ZC
There's probably an autovivification that I'm missing that could simplify this greater.

I suggest you to create another array variable to hold the new items' quantities:
// I imagine these are your existing variables from your sample code
$tallesTotalesC = array('XL','M','XL','S');
$cantidadesTotalesC = array(5,2,4,7);
$uniqueTallesTotalesC = array_unique($tallesTotalesC);
// This will reset the indexes of the unique items array
$uniqueTallesTotalesC = array_values($uniqueTallesTotalesC);
// init a new quantities array with zeros
$uniqueCantidadesTotales = array_fill(0, count($uniqueTallesTotalesC), 0);
if (count($uniqueTallesTotalesC) == count($tallesTotalesC)) {
// all items are unique so no need to loop through and sum the quantities
$uniqueCantidadesTotales = $cantidadesTotalesC;
} else {
foreach($uniqueTallesTotalesC as $newIndex => $item) {
// get all indexes of the item in the old array
$oldIndexes = array_keys($tallesTotalesC, $item);
// for each of the index, get the sum the old quantity to the new quantity
foreach($oldIndexes as $oldIndex) {
$uniqueCantidadesTotales[$newIndex] += $cantidadesTotalesC[$oldIndex];
}
}
}
Hope it helps!

Related

how to sort an array in descending order in php

Newly-entered products are displayed in the last row. If there is a large amount, it is difficult to see at the bottom. How can I change the new display to the top. Thank you!
$barcodes_ary = explode(',', $barcodes);
$barcodes_hash = array ();
foreach ($barcodes_ary as $b) {
if (array_key_exists($b, $barcodes_hash)) {
$barcodes_hash[$b] += 1;
} else {
$barcodes_hash[$b] = 1;
}
}
foreach ($barcodes_hash as $b => $amount) {
if ($barcodes_ary == array(''))continue;
$ary = get_sql("SELECT * FROM Products WHERE Barcode='$b' Order by ProductName");
if ( count($ary) == 0 ) {
continue;
}
$pid = $ary[0]['ProductID'];
$pn = $ary[0]['ProductName'];
$unit = $ary[0]['UnitID'];
$ary2 = get_sql("SELECT UnitName FROM Units WHERE UnitID = '$unit'");
$unit = $ary2[0]['UnitName'];
?>
<TR>
<TD><? echo "$pn"; ?></TD>
<TD>
<INPUT TYPE=hidden NAME=productid<?=$pid?> VALUE='<?=$pid?>'>
<?
$candidates = array();
for($i=1; $i <= DropDownMaxValue; $i++) {
$candidates[]=$i;
}
//update
I use another way to solve the problem. Just display the same product.
function push_barcode() {
// alert('barcode pushing');
b = document.form1.barcode;
bs = document.form1.barcodes;
if (bs.value == "") {
bs.value = b.value;
} else { // ?? 111,333,444,... ???
bs.value = b.value;
}
}
Okay, you should be able to get the count using the keys values returned in reverse in brackets with the array.
Try the following and see if it works for you...
$ProductName = $ary[0]['ProductName'];
//--> get the count of your array
$count = count($ProductName);
//--> define an output variable to hold values
$output = null;
$i = 0;
//--> reduce count by one as key values start at 0 and count starts at 1
$count = $count - 1;
//--> subtraction and addition of $count by one to reduce warning
//--> of `undefined offset` for index on mismatched key values
while($count + 1){
//--> concatenate the values into a variable for display
$output .= $ProductName[$count];
//--> or push the reversed values back into an array
$product_name[$i] = $ProductName[$count];
//--> $product_name should now hold your values in reverse use a foreach
// use a foreach to display values in your table
$count--;
$i++;
}

PHP create array from another array

I have an array which I have received from an API.
object(stdClass)#19498 (4) {
["success"]=>
bool(true)
["quoteId"]=>
int(0011)
["abcValue"]=>
float(00)
["priceResponse"]=>
array(4) {
[0]=>
object(stdClass)#19502 (9) {
["priceId"]=>
int(1263)
["fPrice"]=>
float(37.14)
["grossPrice"]=>
float(44.7)
["priceType"]=>
string(2) "ABC"
}
[1]=>
object(stdClass)#19501 (10) {
["priceId"]=>
int(1263)
["fPrice"]=>
float(37.14)
["grossPrice"]=>
float(44.7)
["priceType"]=>
string(2) "ABC"
}
[2]=>
object(stdClass)#19500 (8) {
["priceId"]=>
int(1266)
["fPrice"]=>
float(550.14)
["grossPrice"]=>
float(544.7)
["priceType"]=>
string(2) "DEF"
}
}
}
I want to loop through the array to add another object in PriceResponse i.e customPrice and also delete some objects from the array like fPrice, priceType etc. The best way I figured to do this was to create another array. However I can't seem to get it working:
PHP:
$output_array = json_decode($output);
$modified_array = array();
$priceResultArray = array();
foreach($output_array as $j => $item) {
foreach($output_array->priceResponse as $i => $field) {
$percent = $field->grossPrice * 10 / 100;
$customPrice = $field->grossPrice + $percent;
$priceResultArray['priceId'] = $field->priceId;
$priceResultArray['customPrice'] = $customPrice;
}
$modified_array['success'] = $output_array->success;
$modified_array['quoteId'] = $output_array->quoteId;
$modified_array['priceResponse'] = $priceResultArray;
}
var_dump($modified_array);
This is the output of the modified array - it only shows the last result of the priceResultArray:
array(3) {
["success"]=>
bool(true)
["quoteId"]=>
int(0011)
["priceResult"]=>
array(5) {
["priceId"]=>
int(1266)
["customPrice"]=>
float(599.17)
}
}
Any pointers would be appreciated.
You don't need the outer loop. $output_array is a single object, not an array. You're looping over the properties, but never doing anything with $j or $item.
And instead of creating a new array, you can simply modify the objects in the original priceResponse array.
$output_array = json_decode($output);
foreach ($output_array->priceResponse as $field) {
$percent = $field->grossPrice * 10 / 100;
$customPrice = $field->grossPrice + $percent;
$field->customPrice = $customPrice;
unset($field->fPrice);
unset($field->priceType);
unset($field->grossPrice);
}
You have such output because you put values inside the same keys within your loop.
You should create new object on each loop interation.
Checkout this code:
$output_array = json_decode($output);
$modified_array = array();
$priceResultArray = array();
foreach($output_array as $j => $item) {
foreach($output_array->priceResponse as $i => $field) {
$percent = $field->grossPrice * 10 / 100;
$customPrice = $field->grossPrice + $percent;
$singlePriceResult = array();
$singlePriceResult['priceId'] = $field->priceId;
$singlePriceResult['customPrice'] = $customPrice;
$priceResultArray[] = $singlePriceResult;
}
$modified_array['success'] = $output_array->success;
$modified_array['quoteId'] = $output_array->quoteId;
$modified_array['priceResponse'] = $priceResultArray;
}
var_dump($modified_array);

Adding to array from multiple foreach statements

I'm trying to add the dynamically generated variables $title and $price to the array $list.
This works to a certain degree. The code creates an array with the keys where they have a title and price value.
The price value is correct and different for each key. However, it seems that only the first title result is added, creating the following array (same title untill key 30)
[0]=> array(2) { ["title"]=> string(57) "Gibson Les Paul ** Nr.1 Gibson dealer ** 18 gitaarwinkels" ["price"]=> string(25) " € 300,00 " } [1]=> array(2) { ["title"]=> string(57) "Gibson Les Paul ** Nr.1 Gibson dealer ** 18 gitaarwinkels" ["price"]=> string(25) " € 100,00 " }
Looking at the code I think it is because the first foreach loop is only executing the second one.
I know the correct values for $title are there, because when I isolate the title foreach loop like this:
foreach ($titlehit as $titles) {
$title = $titles->nodeValue;
echo "$title";
}
30 different $title result are displayed
$url = "https://url.com";
$html = new DOMDocument();
#$html->loadHtmlFile($url);
$xpath = new DOMXPath($html);
$titlehit = $xpath->query("//span[#class='mp-listing-title']");
$pricehit = $xpath->query("//span[#class='price-new']");
$list = array();
$i = 0;
foreach ($titlehit as $titles) {
foreach ($pricehit as $prices) {
if ($i >=5 && $i <=35) {
$title = $titles->nodeValue;
$price = $prices->nodeValue;
$list[] = array(
'title' => $title,
'price' => $price
);
}
$i++;
}
}
How can I get the array $list to hold both the correct title and price values? Thanks for your help.
Assuming that for each title, there is one price i.e there is a 1:1 title-to-price ratio in the corresponding arrays, you will only need 1 loop.
$list = array();
$i = 0; // initialize
// Assuming $titlehit AND $pricehit have the same number of elements
foreach ($titlehit as $titles) {
// Assuming $pricehit is a simple array. If it is an associative array, we need to use the corresponding key as the index instead of $i. We'll get to this once you can confirm the input.
$prices = $pricehit[$i];
// Not entirely sure why you need this condition.
if ($i >=5 && $i <=35) {
$title = $titles->nodeValue;
$price = $prices->nodeValue;
$list[] = array(
'title' => $title,
'price' => $price
);
}
$i++;
}
Not exactly enough code here to know for sure but it looks like you need to reset your iterator $i with each iteration of your foreach loop:
$list = array();
foreach ($titlehit as $titles) {
$i = 0;
foreach ($pricehit as $prices) {
if ($i >=5 && $i <=35) {
$title = $titles->nodeValue;
$price = $prices->nodeValue;
$list[] = array(
'title' => $title,
'price' => $price
);
}
$i++;
}
}

PHP foreach loops and data retrieval

Using PHP and MySQL I have generated two arrays. I would like to loop through these arrays, retrieve data from both and display together in one sentence.
foreach ($items as $item) {
if(isset($item->item_title)) {
$itemTitle = $item->item_title;
}
// var_dump($itemTitle);
// string(7) "Halfway" string(5) "Story" string(6) "Listen"
}
foreach ($aData["Items"]["Item"] as $a) {
if (isset($a['description'])) {
$aDescription = $a['description'];
}
// var_dump($aDescription );
// string(4) "Good" string(6) "Strong" string(2) "OK"
}
?>
Desired result;
The title is Halfway and the description is Good.
The title is Story and the description is Strong.
The title is Listen and the description is OK.
// etc
// etc
Is it possible to nest the foreach loops, or is there a better more efficient way?
Please try this way. Hope this help!!
foreach ($items as $index => $item) {
if(isset($item->item_title)) {
$itemTitle = $item->item_title;
echo 'The title is '.$itemTitle;
}
if(isset($aData["Items"]["Item"][$index]['description']) {
$itemDescription = $aData["Items"]["Item"][$index]['description'];
echo ' and the description is '.$itemDescription;
}
echo '<br>';
// The title is Halfway and the description is Good.
}
You can merge those two foreach loops using a simple for loop, like this:
$count = count($items) >= count($aData["Items"]["Item"]) ? count($aData["Items"]["Item"]) : count($items);
for($i = 0; $i < $count; ++$i){
if(isset($item[$i]->item_title)) {
$itemTitle = $item[$i]->item_title;
}
if (isset($aData["Items"]["Item"][$i]['description'])) {
$aDescription = $aData["Items"]["Item"][$i]['description'];
}
// your code
}
Sidenote: The above code assumes that two arrays $items and $aData["Items"]["Item"] have unequal number of elements, though this will work for equal number of elements as well. If you're sure that these two arrays will always have equal number of elements, then refactor the $count = ... ; statement in the following way,
$count = count($items);
or
$count = count($aData["Items"]["Item"]);
and use this $count variable in for loop.
Try this hope this will help you out.
Note: Here i am assuming both array's have same indexes.
$items
$aData["Items"]["Item"].
If not you can do array_values($items) and array_values($aData["Items"]["Item"])
foreach ($items as $key => $item)
{
if (isset($item->item_title) && isset($aData["Items"]["Item"][$key]['description']))
{
$itemTitle = $item->item_title;
echo sprinf("The title is %s and the description is %s",$itemTitle,$aData["Items"]["Item"][$key]['description']);
echo PHP_EOL;
}
}

how to know if an array of indexed arrays had the same value more than once?

I have this array
$products[0]['productid'] = 5;
$products[0]['name'] = "apples";
$products[0]['seller'] = 1;
$products[1]['productid'] = 15;
$products[1]['name'] = "orange";
$products[1]['seller'] = 1;
$products[2]['productid'] = 5;
$products[2]['name'] = "apples";
$products[2]['seller'] = 2;
// .... more 5000 products
this array is filled by the client with ajax. I need to make a restriction that $products array don't have the same productid in any of it's other members. as in the invalid data example above 5
What I do to get that done is by doing this
$onlyids = array();
for($x=0; $x < count($products); $x++){
$onlyids[]=$products[$x]['productid'];//get only productid in an array
}
//remove duplicate members
$onlyids2= array_unique($onlyids);
//check if there were duplicates
if(count($onlyids) != count($onlyids2)){
//same id found, reject client inputs
}
did I do it correct ? or there is a better performing way. because my way is obviously consume more time on big arrays?
Probably the most performant way is to store found product ids as array keys while you iterate the data:
$productIds = [];
foreach ($products as $product) {
if (isset($productIds[$product['productid']])) {
throw new Exception('Duplicate product id ' . $product['productid']);
}
$productIds[$product['productid']] = true;
}
echo 'All good';
More obscure and inefficient, but a one-liner:
if (max(array_count_values(array_column($products, 'productid'))) > 1) {
throw new Exception('Invalid input');
}

Categories