Find the matched value of an array with a given value - php

I have an array of value series like:
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
Another value getting from DB like:
$point = $data[‘earned_point’];
I need the highest match from the series. such as I got a value from db (1500) the highest match of the value is 1000 in the series, so I need to get the $series[4] and make it
$reward = $series[4] * 0.1;
I'll run it in a loop to do it for all the values got from DB.

I'm posting alternate code as the accepted answer while is correct can be very inefficient if you are working with a large array.
<?php
function computeReward($series, $point, $percent = 0.1){
arsort($series); // sort the series in reverse so we can pass any array and the highest number will be the first because we are looking for a number lower or equal to our point
foreach($series as $min_point){
if($min_point <= $point){
return $min_point * $percent; // return the min_point * the percentage, this stops the loop there for being more efficient
}
}
}
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
$point = $data['earned_point'];
$reward = computeReward($series, $point);
?>

Do you mean you want to get which highest $series item is equal or less than $point ?
<?php
$series = [100,300,500,800,1000,3000,5000,10000,15000,20000];
$point = $data['earned_point'];
foreach ($series as $min_point) {
if ($point >= $min_point) {
$matched_min_point = $min_point;
}
}
$reward = $matched_min_point*0.1;
Let me know if this works for you

Related

Compare one number with numbers in array to find the smallest difference

I have:
$current_price = 100;
$array_price = array(10,20,30,40,50,60,70,80,90, 140,150)
I want to compare the current price with the prices in the array, find the smallest abs difference and save the price from the array that has the smallest difference with the current price
$diff = '';
$diff_array=array();
foreach ($array_price as $value) {
$diff = abs($current_pric - $value);
$diff_array[] = $diff;
}
echo(min($diff_array) . "<br>");
In this case i can find the smallest difference but how i can save the price from the array that is connected with that smallest difference?
You don't need $diff_array. Just loop through the array testing whether the current difference is smaller than the smallest difference seen so far. If so, save the current difference and the current price in variables.
$smallest_element = $array_price[0];
$smallest_diff = abs($smallest_element - $current_price);
for ($i = 1; $i < count($array_price); $i++) {
if (abs($array_price[$i] - $current_price) < $smallest_diff) {
$smallest_diff = abs($array_price[$i] - $current_price);
$smallest_element = $array_price[$i];
}
}
echo "Closest price is $smallest_element\n";
I would approach the problem a little bit different.
Just save the value of the variable if it is lower than the saved one, and also keep the index of the array so you will have the index and the value of the array.
You can approach this by using array_walk with abs and than in difference array use min & array_search retrieve the min array element which is the lower difference
$b = [];
array_walk($array_price, function(&$v,&$k) use ($current_price, &$b){
$b[$v] = abs($current_price - $v);
});
echo 'Minimam array element is : '.array_search(min($b), $b).', which has difference : '.min($b);
Live working example : https://3v4l.org/QasYM

Add up numbers in a for each PHP?

I'm trying to add some numbers in a foreach loop in my PHP code. I am getting a percentage of numbers in a while loop in my MySQL query for each result that I get in my PHP page.
All I need to do is to add up the final values in and show them as total.
This is how I make up the percentage in my while loop in my MySQL query:
$percentage = 10;
$totalWidth = $fees;
$new_width = ($percentage / 100) * $totalWidth;
The $fees value is dynamic and it is different for each result in my while loop. the code above works as it should.
Now I want to add up all the values of $new_width. For example:
If one result's $new_width is 25 and the other one is 10 and another one is 5, I need to do this: $total = 25 + 10 + 5;
So I tried something like this:
$total = 0;
foreach($new_width as $var) {
$total = $var + $var;
}
echo $total;
but the above code doesn't really make sense and it won't do anything at all.
Could someone please advise on this matter?
First you want to change this line in your while loop so you get an array:
$new_width = ($percentage / 100) * $totalWidth;
to this:
//Declare it as an array before your while loop
$new_width = array();
//In your while loop
$new_width[] = ($percentage / 100) * $totalWidth;
//^^ See here
After this you just have to change the line in your foreach loop like this:
$total = $var + $var;
to this:
$total += $var;
(If you want you also can do this in your while loop)
If you have an array of numbers and you want to calculate the sum of those numbers, you should use array_sum().
According to the logic, you are setting the total to 2 X $var.
My answer is very similar, but you add it to the total which is outside of the loop and the value will keep growing:
$total = 0;
foreach($new_width as $var) {
$total += $var;
}
echo $total;
Or simply as stated before, if it is the only value in the array:
$total = array_sum($new_width);

How to tell if a comma delimited list of numbers obeys the natural order of numbers

I have a comma delimited list of numbers which i am converting into an array and what i want to know about the list of numbers is if the numbers listed obey a natural ordering of numbers,you know,have a difference of exactly 1 between the next and the previous.
If its true the list obeys the natural ordering,i want to pick the first number of the list and if not the list obeys not the natural order,i pick the second.
This is my code.
<?php
error_reporting(0);
/**
Analyze numbers
Condition 1
if from number to the next has a difference of 1,then pick the first number in the list
Condition 2
if from one number the next,a difference of greater than 1 was found,then pick next from first
Condition 3
if list contains only one number,pick the number
*/
$number_picked = null;
$a = '5,7,8,9,10';
$b = '2,3,4,5,6,7,8,9,10';
$c = '10';
$data = explode(',', $b);
$count = count($data);
foreach($data as $index => $number)
{
/**
If array has exactly one value
*/
if($count == 1){
echo 'number is:'.$number;
exit();
}
$previous = $data[($count+$index-1) % $count];
$current = $number;
$next = $data[($index+1) % $count];
$diff = ($next - $previous);
if($diff == 1){
$number_picked = array_values($data)[0];
echo $number_picked.'correct';
}
elseif($diff > 1){
$number_picked = array_values($data)[1];
echo $number_picked.'wrong';
}
}
?>
The problem i am having is to figure out how to test the difference for all array elements.
No loops are needed, a little bit of maths will help you here. Once you have your numbers in an array:
$a = explode(',', '5,7,8,9,10');
pass them to this function:-
function isSequential(array $sequence, $diff = 1)
{
return $sequence[count($sequence) - 1] === $sequence[0] + ($diff * (count($sequence) - 1));
}
The function will return true if the numbers in the array follow a natural sequence. You should even be able to adjust it for different spacings between numbers, eg 2, 4, 6, 8, etc using the $diff parameter, although I haven't tested that thoroughly.
See it working.
Keep in mind that this will only work if your list of numbers is ordered from smallest to largest.
Try using a function to solve this... Like so:
<?php
error_reporting(0);
/**
Analyze numbers
Condition 1
if from number to the next has a difference of 1,then pick the first number in the list
Condition 2
if from one number the next,a difference of greater than 1 was found,then pick next from first
Condition 3
if list contains only one number,pick the number
*/
$number_picked = null;
$a = '5,7,8,9,10';
$b = '2,3,4,5,6,7,8,9,10';
$c = '10';
function test($string) {
$data = explode(',', $string);
if(count($data) === 1){
return 'number is:'.$number;
}
foreach($data as $index => $number)
{
$previous = $data[($count+$index-1) % $count];
$current = $number;
$next = $data[($index+1) % $count];
$diff = ($next - $previous);
if($diff == 1){
$number_picked = array_values($data)[0];
return $number_picked.'correct';
}
elseif($diff > 1){
$number_picked = array_values($data)[1];
return $number_picked.'wrong';
}
}
}
echo test($a);
echo test($b);
echo test($c);
?>
You already know how to explode the list, so I'll skip that.
You already handle a single item, so I'll skip that as well.
What is left, is checking the rest of the array. Basically; there's two possible outcome values: either the first element or the second. So we'll save those two first:
$outcome1 = $list[0];
$outcome2 = $list[1];
Next, we'll loop over the items. We'll remember the last found item, and make sure that the difference between the new and the old is 1. If it is, we continue. If it isn't, we abort and immediately return $outcome2.
If we reach the end of the list without aborting, it's naturally ordered, so we return $outcome1.
$lastNumber = null;
foreach( $items as $number ) {
if($lastNumber === null || $number - $lastNumber == 1 ) {
// continue scanning
$lastNumber = $number;
}
else {
// not ordened
return $outcome2;
}
}
return $outcome1; // scanned everything; was ordened.
(Note: code not tested)
To avoid the headache of accessing the previous or next element, and deciding whether it still is inside the array or not, use the fact that on a natural ordering the item i and the first item have a difference of i.
Also the corner case you call condition 3 is easier to handle outside the loop than inside of it. But easier still, the way we characterize a natural ordered list holds for a 1-item list :
$natural = true;
for($i=1; $i<$count && $natural; $i++)
$natural &= ($data[$i] == $data[0] + $i)
$number = $natural ? $data[0] : $data[1];
For $count == 1 the loop is never entered and thus $natural stays true : you select the first element.

Adding data from an array to a new array

I have created an array of data, from which I can loop through specific fields and echo these values out, but what I need to do is add these values to a new array, ultimately allowing me to find the average of the values in the new array. As i've said, I can echo out the data, and I think I've figured how to get the average, if only I can create the new array! Any help would be greatly appreciated as I just can't find the answer anywhere, and I'm running low on talent!
My table contains approx 25 fields, im pulling out a number of rows based on a session variable. In the instance im working on, I need to take just the values from 1 column in the table, and add these to an array. The code below will loop through the values, and echo them out, 1 at a time:-
while ($cdarray=mysql_fetch_array($calldata)) {
echo $cdarray['score_total'];
}
This gives me 25555 which are the 4 values I would expect 25, 5, 5, 5
I've tried
while ($cdarray=mysql_fetch_array($calldata)) {
$cdts = $cdarray['score_total'];
$cdtsar = array($cdts);
}
Which results in $cdts being assigned a value of 5,
Any help greatly appreciated!!
This will get your data from the array, place it into a new one and calculates the average.
$cdtsar = array();
while ($cdarray=mysql_fetch_array($calldata)) {
$cdtsar[] = $cdarray['score_total'];
}
$average = array_sum($cdtsar) / count($cdtsar);
It actually prints 25 and 5 and 5 and 5, but there are no spaces in between so it looks like "25555". To verify this yourself:
while ($cdarray=mysql_fetch_array($calldata)) {
echo $cdarray['score_total'];
echo " / ";
}
To get the average, you can either use
$sum = $count = 0;
$average = null;
while ($cdarray=mysql_fetch_array($calldata)) {
$sum += $cdarray['score_total'];
++$count;
}
// Make sure to guard against divide by zero
if ($count) {
$average = $sum / $count;
}
or you might have the database calculate the average for you, if changing the query is an option.
If you want to assign the elements to the new array use like this
$cdtsar = array();
while ($cdarray=mysql_fetch_array($calldata)) {
array_push($cdtsar,$cdarray['score_total']);
}
To find the average of the array
$sum = array_sum($cdtsar);
$num = sizeof($cdtsar);
$avg = $sum/$num;
echo $avg;

Function generating Unique Random Values Array

As Mysql rand() is time consuming I am using alternate way using Mysql max() and PHP. I wrote this code for fetching random product_id's:
function RandomUniqueArray($min,$max,$limit){
$random_array = array();
if(isset($limit) && is_numeric($limit)){
for($i=0;$i<$limit;){
$rand_val = mt_rand($min, $max);
if(!in_array($rand_val, $random_array)){
$random_array[] = $rand_val;
$i++;
}
}
}
return $random_array;
}
This works fine as I want each time it gives different result set with different unique values but it takes 6.232 micro seconds.
Ohter I got by Google is:
$random_array = array_rand(array_fill($min,$max, true),$limit);
with takes only 0.101 microseconds but its result set is repeated means. Unique values array is fine but whole set is repeated. Why is it so???
I called both of these by one by one as
$random_array = RandomUniqueArray(1,64000,4);
And
$random_array = array_rand(array_fill(1,64000, true),4);
Thank you.
I made a script,that only takes ̣̣̣+- 4.5E-6.
Try it.
function randomValue($min,$max,$limit)
{
$array = Array();
$MAX = mt_rand($min,$max);
for($i = 0;$i < $limit;$i++)
{
$array[$i] = mt_rand($min,$MAX);
while( is_array($array[$i],$array) ) //To check if exist, if. Make new.
{
$array[$i] = mt_rand($min,$MAX);
}
}
return $array;
}

Categories