Get the highest number value 'Magento' - php

I have this function and i want to get the highest number value.
$array is out-putting 20, 50, 40.
I want to print 50 only not the other 2.
Tried everything nothing is working.
foreach ($products as $product) {
$originalPriceCat = $product->getPrice();
$finalPriceCat = $product->getFinalPrice();
if ($originalPriceCat > $finalPriceCat) {
$CalculatedPrice = ($originalPriceCat - $finalPriceCat) * 100 /$originalPriceCat;
$array = array($CalculatedPrice);
echo round(max($array));
}
}

The following code will surely solve your problem
$CalculatedPrice = array();
foreach ($products as $product) {
$originalPriceCat = $product->getPrice();
$finalPriceCat = $product->getFinalPrice();
if ($originalPriceCat > $finalPriceCat) {
$CalculatedPrice[] = ($originalPriceCat - $finalPriceCat) * 100 / $originalPriceCat;
}
}
echo round(max($CalculatedPrice));

Take a look at this php function: max
max ( array $values ) : mixed
max ( mixed $value1 [, mixed $... ] ) : mixed
If the first and only parameter is an array, max() returns the highest
value in that array. If at least two parameters are provided, max()
returns the biggest of these values.
max() returns the parameter value considered "highest" according to standard comparisons.
If multiple values of different types evaluate as equal (e.g. 0 and 'abc') the first provided to the function will be returned.
If an empty array is passed, then FALSE will be returned and an E_WARNING error will be emitted.

Related

How do I Destroy a Static Variable in PHP?

The answers to this question say that unset() doesn't work, but weren't clear on what does. I have a recursive function, which uses static variables, however after the recursion has finished and the value has been returned, I need to reset those variables or subsequent calls (the recursive function is currently been called within a loop) would return wrong values.
In the linked question some people suggested trying $var = NULL outside the function which I did, but to seemingly no effect.
The reason why I used static variables and didn't just write them as parameters to the function is that I don't want a situation where the user can pass in arguments to that function, as the only arguments to the function should be supplied from within it.
My Code
<?
require_once("randX.php"); #"randX()" generates a random floating point number in a specified range.
// require_once("../displayArray.php");
error_reporting(E_ERROR | E_WARNING | E_PARSE);
/*
* Generates a valid, random probability distribution for a given array of elements, that can be used in conjunction with "probSelect()".
* Input:
$arr: An array of elements.
$control: A value that decides how much mass is allowed to be unilaterally dumped onto one element. A high value would permit distributions where most of the mass is concentrated on one element.
If an invalid value is provided, the default is used.
* Output: An associative array where the keys are the elements in the original array, and the values are their probabilities.
* #param array $arr: An array of elements for which the probability distribution would be generated.
* #param float $control: A variable which limits the inequality of the probability distribution.
*/
function probGen(array $arr, float $control = 0.01)
{
$control = ($control <= 1 && $control >= 0)?($control):(0.00001); #Use the default value if an invalid number is supplied.
static $result = []; #Initialises $result with an empty array on first function call.
static $max = 1; #Initialises $max with 1 on first function call.
foreach ($arr as $value)
{
$x = randX(0, $max); #Random probability value.
$result[$value] = ($result[$value] + $x)??0; #Initialise the array with 0 on first call, and on subsequent calls increment by $x to assign probability mass.
$max -= $x; #Ensures that the probability never sums to more than one.
}
/*
* After the execution of the above code, there would be some leftover probability mass.
* The code below adds it to a random element.
*/
$var = array_values($arr);
if($max <= $control) #To limit concentration of most of the probability mass in one variable.
{
$result[$var[rand(0,(count($var)-1))]] += $max; #Selects a random key and adds $max to it.
// print("<br>Sum: ".array_sum($result)."<br>");
return $result;
}
else
{
return probGen($arr, $control);
}
}
$max = NULL;
unset($max);
$result = NULL;
unset($result);
?>
This is always the problem with using static in any circumstances, I would change them to be parameters being passed in and having a default value...
function probGen(array $arr, float $control = 0.01, $result = [], $max = 1 )
(With the appropriate types).
These can then be passed down the chain in your further call...
return probGen($arr, $control, $result, $max);
This allows you better control over what these values start as (you can pass in your own values as a default) as well as being able to reset/adjust them as part of the call.

How to sort an array contains complex strings with fractions in php?

I have the following values in an array,
$values = array(
"1/4x1/4x1",
"1/2x1/2x1",
"3/4x3/4x1",
"1/4x1/4x2",
"1/2x1/2x2",
"3/4x3/4x2",
"1x1x1",
"1x2x1",
"2x1x1"
);
Considering the numbers in between 'x', I want the ascending order of the values as the following,
$values = array(
"1/4x1/4x1",
"1/4x1/4x2",
"1/2x1/2x1",
"1/2x1/2x2",
"3/4x3/4x1",
"3/4x3/4x2",
"1x1x1",
"1x2x1",
"2x1x1"
);
I'm new to PHP. Are there any specific functions for this? If not, please help with a way to find a solution. Thanks.
It is a bit complex, but you can avoid using eval:
// Transpose resulting 2x2 matrix using array_map behavior of
// tacking an arbitrary number of arrays and zipping elements, when null
// giving as a callback.
$evaluated = array_map(null, ...array_map(function ($factors) {
return array_map(function ($factor) {
// Explode fraction (into array with two elements)
// and destruct it into variables.
// `#` will silent the notice if not a fraction given (array with one
// element).
#list($dividend, $divisor) = explode('/', $factor); // **
// If divisor is given then calculate a fraction.
return $divisor
? floatval($dividend) / floatval($divisor)
: floatval($dividend);
}, explode('x', $factors));
}, $values));
// Assign values array by reference as a last element.
$evaluated[] =& $values;
// Unpack all arrays (three columns of fractions and given array) and pass
// them to `array_multisort` function, that will sort in turns by each of
// the columns.
array_multisort(...$evaluated);
print_r($values);
So, basically, we map each item from the array into an array of calculated fractions and then transpose this array to end up with three arrays representing columns. Then we pass this three array along with given array into array_multisort, that takes the given array by reference and reorders it as we want.
Here is the demo.
Don't use eval()! It is evil. And you can avoid it easily. You need to create a callback method for usort() that compares the dimensions (and if necessary converts fractions to numeric values).
I assume you always have 3 dimensions and they are either a positive integer or a fraction. I also assume that you are not sorting by volume but by dimension 1, dimension 2, dimension 3.
/**
* usort callback to sort dimensions
* #param {string} $a first comparable value
* #param {string} $b second comparable value
* #returns {int} 0, 1 or -1
*/
function sortByDimension($a, $b) {
$dimA = getNumericDimensions($a);
$dimB = getNumericDimensions($b);
// first dimension is the same: compare deeper
if ($dimA[0] == $dimB[0]) {
// second dimension is the same too: compare deeper
if ($dimA[1] == $dimB[1]) {
if ($dimA[2] == $dimB[2]) {
// value is the same: return 0
return 0;
}
// value A is larger: return 1, value B is larger: return -1
return ($dimA[2] > $dimB[2]) ? 1 : -1;
}
return ($dimA[1] > $dimB[1]) ? 1 : -1;
}
return ($dimA[0] > $dimB[0]) ? 1 : -1;
}
/**
* converts a string value to an array of numeric values
* #param {string} $val string of dimensions AxBxC
* #returns {array} an array with 3 dimensions and numeric values
*/
function getNumericDimensions($val) {
// split the value into the 3 dimensions
$dimensions = explode('x', $val);
// loop through the values and make them numeric
// note: the loop is per reference: we override the values!
foreach ($dimensions as &$dim) {
// check if it is a fraction
if (strpos($dim, '/') !== false) {
// split the fraction by the /
$fraction = explode('/', $dim);
// calculate a numeric value
$dim = $fraction[0] / $fraction[1];
} else {
// make it an integer
$dim = (int)$dim;
}
}
return $dimensions;
}
$values = array(
"1/4x1/4x1",
"1/2x1/2x1",
"3/4x3/4x1",
"1/4x1/4x2",
"1/2x1/2x2",
"3/4x3/4x2",
"1x1x1",
"1x2x1",
"2x1x1",
);
// sort the array (note: usort is per reference)
usort($values, 'sortByDimension');
print_r($values);

PHP: counting all the items of a multilevel array containing a given parameter and a given value

I'm trying to build a function to count all the items of an array containing a given parameter, but, if the parameter is not given when calling the function, the function should count all the items. Parameters are passed with an array $params: This is what I have done so far:
function myfunction($params){
global $myArray;
if ( !isset($params[0]) ){ $params[0] = ???????? } // I need a wildcard here, so that, if the parameter is not given, the condition will be true by default
if ( !isset($params[1]) ){ $params[1] = ???????? } // I need a wildcard here, so that, if the parameter is not given, the condition will be true by default
....etc......
foreach($myArray as $item){
if ($item[0] == $params[0]){ // this condition should be true if parameter is not given
if ($item[1] == $params[1]){// this condition should be true if parameter is not given
$count += $item
}
}
}
return $count;
}
I would like:
myfunction(); //counts everything
myfunction( array ('0' => 'banana') ); //counts only $myArray['0'] = banana
myfunction( array ('0' => 'apple', '1' => 'eggs') ); //counts only $myArray['0'] = apples and $myArray['1'] = eggs
I have several $params[keys] to check this way.
I guess, if I should assign a default value to params[key] (like a wildcard) , so that, if it is not given, the function will take all the $item. I mean something that $item[0] will always be (==) equal to. Thanks. [See my answer for solution]
The way your function is declared, you have to pass a parameter. What you want to do is have a default value so that your code inside the function can detect that:
function myfunction($params=NULL)
{
global $myArray;
if (empty($params))
{
// count everything
}
else
{
// count what's listed in the $params array
}
}
EDIT
If I read your comments correctly, $myArray looks something like this:
$myArray=array
(
'apple'=>3, // 3 apples
'orange'=>4, // 4 oranges
'banana'=>2, // 2 bananas
'eggs'=>12, // 12 eggs
'coconut'=>1, // 1 coconut
);
Assuming that's true, what you want is
function myfunction($params=NULL)
{
global $myArray;
$count=0;
if (empty($params)) // count everything
{
foreach ($myArray as $num) // keys are ignored
$count += $num;
}
else if (!is_array($params)) // sanity check
{
// display an error, write to error_log(), etc. as appropriate
}
else // count what's listed in the $params array
{
foreach ($params as $key) // check each item listed in $params
if (isset($myArray[$key])) // insure request in $myArray
$count += $myArray[$key]; // add item's count to total
}
return $count;
}
This will give you
myfunction(); // returns 22
myfunction(array('banana')); // returns 2
myfunction(array('apple','eggs')); // returns 15
myfunction(array('tomatoes')); // returns 0 - not in $myArray
If this isn't the result you're looking for, you need to rewrite your question.
EDIT # 2
Note that because arrays specified without explicit keys are keyed numerically in the order the elements are listed, the function calls I showed above are exactly equivalent to these:
myfunction(); // returns 22
myfunction(array(0=>'banana')); // returns 2
myfunction(array(0=>'apple',1=>'eggs')); // returns 15
myfunction(array(0=>'tomatoes')); // returns 0 - not in $myArray
However, the calls are not equivalent to these:
myfunction(); // returns 22
myfunction(array('0'=>'banana')); // returns 2
myfunction(array('0'=>'apple','1'=>'eggs')); // returns 15
myfunction(array('0'=>'tomatoes')); // returns 0
In this case, explicit string keys are specified for the array, and while the strings' values will evaluate the same as the numerical indices under most circumstances, string indices are not the same as numerical ones.
The code you proposed in your answer has a few errors:
foreach($myArray as $item)
{
foreach ($params as $key => $value)
{
if ( isset($params[$key]) && $params[$key] == $item[$key] )
{
$count += $item
}
}
}
First, isset($params[$key]) will always evaluate to TRUE by the nature or arrays and foreach. Second, because of your outer foreach loop, if your $myArray is structured as I illustrated above, calling myfunction(array('apple')) will result in $params[$key] == $item[$key] making these tests because $key is 0:
'apple' == 'apple'[0] // testing 'apple' == 'a'
'apple' == 'orange'[0] // testing 'apple' == 'o'
'apple' == 'banana'[0] // testing 'apple' == 'b'
'apple' == 'eggs'[0] // testing 'apple' == 'e'
'apple' == 'coconut'[0] // testing 'apple' == 'c'
As you can see, this will not produce the expected results.
The third problem with your code is you don't have a semicolon at the end of the $count += $item line, so I'm guessing you didn't try running this code before proposing it as an answer.
EDIT # 3
Since your original question isn't terribly clear, it occurred to me that maybe what you're trying to do is count the number of types of things in $myArray rather than to get a total of the number of items in each requested category. In that case, the last branch of myfunction() is even simpler:
else // count what's listed in the $params array
{
foreach ($params as $key) // check each item listed in $params
if (isset($myArray[$key])) // insure request in $myArray
$count++; // add the item to the total
}
With the sample $myArray I illustrated, the above change will give you
myfunction(); // returns 5
myfunction(array('banana')); // returns 1
myfunction(array('apple','eggs')); // returns 2
myfunction(array('tomatoes')); // returns 0 - not in $myArray
Again, if neither of these results are what you're looking for, you need to rewrite your question and include a sample of $myArray.
MY SOLUTION
(Not extensively tested, but works so far)
Following #FKEinternet answer, this is the solution that works for me: obviously the $params should use the same keys of $item. So, foreach iteration if parameter['mykey'] is given when calling the function and its value is equal to item['mykey'], count the iteration and $count grows of +1
function myfunction($params=NULL){
global $myArray;
foreach($myArray as $item){
foreach ($params as $key => $value){
if ( isset($params[$key]) && $params[$key] == $item[$key] ){
$count += $item;
}
}
}
return $count;
}
Thanks everybody for all inputs!!

PHP counter excluding zeros

In PHP I have an array that returns a set of values. I want to count the number of instances in the array excluding the zeros. Basically I'm creating an average total column in a table and if a person did not contribute then I don't want to count them. I have the total amount, just not the total count that contributes. Any help please?
You can do it with count and array_filter method.
count gives you the total number of elements in an array.
array_filter removes all elements whose value represents false(such as 0 empty string etc.) from an array;
Eg:
echo count(array_filter($your_array));
Use foreach to iterate the array and count the items that are not "zero".
$counter = 0;
foreach ($array as $item) {
if ( /* determine if $item is "not zero" */ ) {
++$counter;
}
}
echo $counter;
That's all I can tell you based on the information you provided.
You can give a callback function to array_filter as the second parameter. (http://php.net/manual/en/function.array-filter.php)
array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
So you can do something like this:
function isNonZero(int $num){
return $num !== 0;
}
count(array_filter([0,1,2,3,4], "isNonZero")); // => 4

Remove first 100 element of variable?

I have this code which stores values in $products. I'm not sure if $products is an array or other thing.
I need to remove the first 100 values.
// Get all products
$products = Product::getProducts(1, 0, 1000000, 'id_product', 'DESC', false, true, $context);
if (is_array($products))
$products = array_slice($product, 100);
Refer to this page to get in deep.
According to array_slice() menu, the signature is:
array array_slice ( array $array , int $offset [, int $length = NULL [, bool $preserve_keys = false ]] )
Since OP wants to remove first 100 elements, it should be:
$first_100_elements = array_slice($products, 0, 100);
First of all, you need to know if the return type of method Product::getProducts(). You can do it using gettype() or even var_dump().
If it is an array, use something like this:
$productsWithoutFirst100 = array_slice($product, 100);
I will get all the elements of the array, from hundredth element, till the end, excluding the first 100 (from key 0 to 99).
It is a collection of products, so it can be a object that implements Iterable interface. If it is the case, the array_slice function will not work. You can put the object into a foreach, and work on it:
$productsArrayWithoutFirst100 = [];
foreach($products as $key =>$product){
if($key >= 100) $productsArrayWithoutFirst100 = $product;
}
Thats a idea, but there is another ways to achieve it. Hope it helps.

Categories