I've created an array with 'maximum' values in.
$management = array(
'100' => '1',
'500' => '2',
'1000' => '3',
);
And created a loop to find the closest value, rounding it up.
$speed = 10;
$r= '';
sort($management);
foreach($management as $mgmt => $name) {
if($mgmt >= $speed) {
$r= $name;
}
}
$r= end($management);
So, where the $speed is 10, it should pick up the array key 100 and if it was 100 it should still pickup 100 but if the speed was 200, it would pickup 500
The above is picking up 500 when the $speed is 10 though.
Can anyone help please?
You have a couple of problems with your code. Firstly, the call to sort rewrites all the keys of the $management array which you are using for the comparison; you need to use ksort instead to sort by the keys instead of the values. Secondly, since the keys are in ascending order, once one is greater than the $speed value, they all will be, so you need to break from the loop once you find a higher value. Try this instead:
$r= '';
ksort($management);
foreach($management as $mgmt => $name) {
if($mgmt >= $speed) {
$r= $name;
break;
}
}
echo $r;
Demo on 3v4l.org
this is an example on how you can do it :
$array = array(1, 10, 100, 200, 400, 500, 1000);
public function getArrayRoundUp($array, $number) {
sort($array);
foreach ($array as $a) {
if ($a >= $number) return $a;
}
return end($array);
}
$value = 950;
$nearest = getArrayRoundUp($array, $value);
//the expect result will be 1000
echo $nearest;
Use the following function
function find(array $array, $search)
{
$last = null; // return value if $array array is empty
foreach ($array as $key => $value) {
if ($key >= $search) {
return $key; // found it, return quickly
}
$last = $key; // keep the last key thus far
}
return $last;
}
Tested and Working:-
echo find($management, 100); // Will result 100
echo find($management, 200); //Will result 500
Related
I am trying to return the highest percentage value along with all the other information like name,average, percentage, color etc in the array.
foreach ($array as $value) {
$name = getName($value);
$average = getAverage($value);
$percentage = getPercentage($value);
$color = getColor($value);
return $percentage;
}
How can i implement the solution to find the desired value (highest percentage) and return it If an array. I am thinking sorting can be one way but i am still not clear how should i do it.
Try this
$percentage1=0;
$datas=array();
foreach ($array as $value) {
$name = getName($value);
$average = getAverage($value);
$percentage = getPercentage($value);
$color = getColor($value);
if($percentage>$percentage1)
{
$percentage1=$percentage;
$datas['name']=$name;
$datas['average']=$average;
$datas['percentage']=$percentage;
$datas['color']=$color;
}
return $datas;
}
Though the code in your question doesn't make any sense, you can use php max function to get highest value if all value in array are numbers.
For example:
<?php $highest_value = max($array); ?>
If you want to use the buit-in PHP sorting, you can use usort(). It use a custom function to sort your array.
usort($array, function($a, $b){
$percentage_a = getPercentage($a);
$percentage_b = getPercentage($b);
if($percentage_a === $percentage_b) {
return 0;
}
return ($percentage_a > $percentage_b)? -1 : 1;
});
return array(
"name" => getName($array[0]),
"average" => getAverage($array[0]),
"percentage" => getPercentage($array[0]),
"color" = getColor($array[0]));
Then, your array is sorted with the highest percentage first.
If you don't want anonymous function, you can juste define it and call usort with its name :
function getMaxPercentage($a, $b){
$percentage_a = getPercentage($a);
$percentage_b = getPercentage($b);
if($percentage_a === $percentage_b) {
return 0;
}
return ($percentage_a > $percentage_b)? -1 : 1;
}
usort($array, 'getMaxPercentage');
return return array(
"name" => getName($array[0]),
"average" => getAverage($array[0]),
"percentage" => getPercentage($array[0]),
"color" = getColor($array[0]));
First, i created an array of, let`s say, 6 elements. Then i randomly pick 4 elements that are GOOD (on random position i mean).
Now, i want to randomly pick 2 out of those 4 selected that are VERY GOOD.
If the value of array1 is the same with array2, then i want it to say VERY GOOD. Else, say GOOD. If the value is 0, then BAD.
I tried allpossibilities and all failed.
This is my last attempt of doing so...
$array1 = array();
$array2 = array();
while (count($array1) < 4) {
$rand = rand(1,6);
if (!isset($array1[$rand])) {
$array1[$rand] = TRUE;
}
}
while (count($array2) < 2) {
$rand = rand(1,4);
if (!isset($array2[$rand])) {
$array2[$rand] = TRUE;
}
}
$array2 = $array2 + array_fill(1, 4, FALSE);
$array1 = $array1 + array_fill(1, 6, FALSE);
ksort($array1);
ksort($array2);
foreach($array1 as $k => $v){
if ($v != 0)
{echo "GOOD<br>";}
else {echo "BAD<br>";}}
foreach($array2 as $kc => $vc){
if ($v2 !=0)
{echo "VERY GOOD<br>";}
else {echo "BAD<br>";}}
This is what it gives me:
GOOD
GOOD
BAD
GOOD
GOOD
BAD
VERY GOOD
BAD
BAD
VERY GOOD
As you can see, it gave me 4/6 GOODS and then 2/6 VERY GOODS.
What i wanted was 4/6 GOODS and from those 4 selected i want 2/4 VERY GOODS.
How can i do this?
Thanks in advance,
Vlad
You want one array of size 6 so why are you creating multiple? You can either merge them in some fashion or use the first in construction of the second.
But first, I want to point out that the while() loops are very similar, so it should be easy to put that into a function and save some code to write and have a codebase that is better manageable, as you only need to edit one place to have immediate effect instead of many.
Now for the first task, all you need is the $number of elements to be created and the $range. This function will do what one of your while() loops did plus the array_fill(). (demo)
function fillRandom($range, $num = 1) {
$data = array_fill($range[0], $range[1]+1, FALSE);
for ($i=0; $i<$num; $i++) {
do {
$key = mt_rand($range[0], $range[1]);
} while ($data[$key] === TRUE);
$data[$key] = TRUE;
}
return $data;
}
Now comes the more advanced part: In the second run, we can identify 2 out of the 4 TRUE in the array of 6 elements by giving them another $value (as an example).
The $data will be needed in some cases and by using an $anonymous function we can allow the condition for the while() to be passed.
function fillRandom($range, $num = 1, $value = TRUE, $data = array(), $anon = NULL) {
if (empty($data))
$data = array_fill($range[0], $range[1]+1, FALSE);
if ($anon === NULL) {
$anon = function($el) use($value) {
return $el !== $value;
};
}
for ($i=0; $i<$num; $i++) {
do {
$key = mt_rand($range[0], $range[1]);
} while (isSet($data[$key]) && !$anon($data[$key]));
$data[$key] = $value;
}
return $data;
}
You can then do something like this (demo)
$input = fillRandom(array(0, 5), 4);
ksort($input);
print_r($input);
$input = fillRandom(array(0, 5), 2, 2, $input, function($el){
return $el === TRUE;
});
ksort($input);
print_r($input);
Is there an equivalent min() for the keys in an array?
Given the array:
$arr = array(300 => 'foo', 200 => 'bar');
How can I return the minimum key (200)?
Here's one approach, but I have to imagine there's an easier way.
function minKey($arr) {
$minKey = key($arr);
foreach ($arr as $k => $v) {
if ($k < $minKey) $minKey = $k;
}
return $minKey;
}
$arr = array(300 => 'foo', 200 => 'bar');
echo minKey($arr); // 200
Try this:
echo min(array_keys($arr));
Try with
echo min(array_keys($arr));
min() is a php function that will return the lowest value of a set. array_keys() is a function that will return all keys of an array. Combine them to obtain what you want.
If you want to learn more about this two functions, please take a look to min() php guide and array_keys() php guide
use array_search() php function.
array_search(min($arr), $arr);
above code will print 200 when you echo it.
For echoing the value of lowest key use below code,
echo $arr[array_search(min($arr), $arr)];
Live Demo
This also would be helpful for others,
<?php
//$arr = array(300 => 'foo', 200 => 'bar');
$arr = array("0"=>array('price'=>100),"1"=>array('price'=>50));
//here price = column name
echo minOfKey($arr, 'price');
function minOfKey($array, $key) {
if (!is_array($array) || count($array) == 0) return false;
$min = $array[0][$key];
foreach($array as $a) {
if($a[$key] < $min) {
$min = $a[$key];
}
}
return $min;
}
?>
$arr = array(
300 => 'foo', 200 => 'bar'
);
$arr2=array_search($arr , min($arr ));
echo $arr2;
I am attempting to find the closest product to the given budget
$array = array(
'productname1' => 5,
'productname2' => 10,
'productname3' => 15
)
$budget = 12;
I have tried using a function like the following to find the nearest value, but it only returns the number which is closest to the budget rather than the product name.
function closest($array, $number) {
sort($array);
foreach ($array as $a) {
if ($a >= $number) return $a;
}
return end($array);
}
I can't help but think there is a MUCH better implementation of this. Any help would be much appreciated.
foreach($array as $k => $v){ $diff[abs($v - $budget)] = $k; }
ksort($diff, SORT_NUMERIC);
$closest_key = current($diff);
var_dump($closest_key); // Product Name
var_dump($array[$closest_key]); // Product Cost
Prints:
string(12) "productname2"
int(10)
Or as a function:
function closest($array, $price)
{
foreach($array as $k => $v){ $diff[abs($v - $price)] = $k; }
ksort($diff, SORT_NUMERIC);
$closest_key = current($diff);
return array($closest_key, $array[$closest_key]);
}
print_r(closest($array, $budget));
Prints:
Array
(
[0] => productname2 // Product Name
[1] => 10 // Product Price
)
Both formats include only three steps:
Calculate the difference between the product cost and the budget
Sort these
Take the first element from the sorted array (the element whose price is closest to the budget).
EDIT: If you don't care about anything other than the single closest product, then a sort is overkill and a simple min() function (like Emil used) would be a lot faster. For example:
function closest($array, $price)
{
foreach($array as $k => $v){ $diff[abs($v - $price)] = $k; }
$closest_key = $diff[min(array_keys($diff))];
return array($closest_key, $array[$closest_key]);
}
function closest($array, $number) {
sort($array);
foreach ($array as $name => $a) {
if ($a >= $number) return $name;
}
return end(array_keys($array));
}
The trick comes in on this line:
foreach ($array as $name => $a) {
Here you assign $name to the array key and $a to the array value. Since you want the name, return $name;
Also, if no match is found, do, end(array_keys($array))); to get the name of the product, otherwise it will just spit out the value, which is not what you want.
You'll want to return the KEY, not the value:
function closest($array, $number) {
sort($array);
foreach ($array as $product=>$a) {
if ($a >= $number) return $product;
}
return $product;
}
Here's a functional way of doing it.
Map each post to the difference from the budget.
Find the smallest value.
Filter away all products not adhering to that value.
Implementation:
$diffs = array_map(function ($value) use ($budget) {
return abs($value - $budget);
}, $array);
$smallest = min($diffs);
$products = array_filter($array,
function ($value) use ($budget, $smallest) {
return abs($value - $budget) == $smallest;
});
$products will now contain all the products which are closest to the budget.
What is the most efficient way to check if an array is a flat array
of primitive values or if it is a multidimensional array?
Is there any way to do this without actually looping through an
array and running is_array() on each of its elements?
Use count() twice; one time in default mode and one time in recursive mode. If the values match, the array is not multidimensional, as a multidimensional array would have a higher recursive count.
if (count($array) == count($array, COUNT_RECURSIVE))
{
echo 'array is not multidimensional';
}
else
{
echo 'array is multidimensional';
}
This option second value mode was added in PHP 4.2.0. From the PHP Docs:
If the optional mode parameter is set to COUNT_RECURSIVE (or 1), count() will recursively count the array. This is particularly useful for counting all the elements of a multidimensional array. count() does not detect infinite recursion.
However this method does not detect array(array()).
The short answer is no you can't do it without at least looping implicitly if the 'second dimension' could be anywhere. If it has to be in the first item, you'd just do
is_array($arr[0]);
But, the most efficient general way I could find is to use a foreach loop on the array, shortcircuiting whenever a hit is found (at least the implicit loop is better than the straight for()):
$ more multi.php
<?php
$a = array(1 => 'a',2 => 'b',3 => array(1,2,3));
$b = array(1 => 'a',2 => 'b');
$c = array(1 => 'a',2 => 'b','foo' => array(1,array(2)));
function is_multi($a) {
$rv = array_filter($a,'is_array');
if(count($rv)>0) return true;
return false;
}
function is_multi2($a) {
foreach ($a as $v) {
if (is_array($v)) return true;
}
return false;
}
function is_multi3($a) {
$c = count($a);
for ($i=0;$i<$c;$i++) {
if (is_array($a[$i])) return true;
}
return false;
}
$iters = 500000;
$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
is_multi($a);
is_multi($b);
is_multi($c);
}
$end = microtime(true);
echo "is_multi took ".($end-$time)." seconds in $iters times\n";
$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
is_multi2($a);
is_multi2($b);
is_multi2($c);
}
$end = microtime(true);
echo "is_multi2 took ".($end-$time)." seconds in $iters times\n";
$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
is_multi3($a);
is_multi3($b);
is_multi3($c);
}
$end = microtime(true);
echo "is_multi3 took ".($end-$time)." seconds in $iters times\n";
?>
$ php multi.php
is_multi took 7.53565130424 seconds in 500000 times
is_multi2 took 4.56964588165 seconds in 500000 times
is_multi3 took 9.01706600189 seconds in 500000 times
Implicit looping, but we can't shortcircuit as soon as a match is found...
$ more multi.php
<?php
$a = array(1 => 'a',2 => 'b',3 => array(1,2,3));
$b = array(1 => 'a',2 => 'b');
function is_multi($a) {
$rv = array_filter($a,'is_array');
if(count($rv)>0) return true;
return false;
}
var_dump(is_multi($a));
var_dump(is_multi($b));
?>
$ php multi.php
bool(true)
bool(false)
For PHP 4.2.0 or newer:
function is_multi($array) {
return (count($array) != count($array, 1));
}
I think this is the most straight forward way and it's state-of-the-art:
function is_multidimensional(array $array) {
return count($array) !== count($array, COUNT_RECURSIVE);
}
After PHP 7 you could simply do:
public function is_multi(array $array):bool
{
return is_array($array[array_key_first($array)]);
}
You could look check is_array() on the first element, under the assumption that if the first element of an array is an array, then the rest of them are too.
I think you will find that this function is the simplest, most efficient, and fastest way.
function isMultiArray($a){
foreach($a as $v) if(is_array($v)) return TRUE;
return FALSE;
}
You can test it like this:
$a = array(1 => 'a',2 => 'b',3 => array(1,2,3));
$b = array(1 => 'a',2 => 'b');
echo isMultiArray($a) ? 'is multi':'is not multi';
echo '<br />';
echo isMultiArray($b) ? 'is multi':'is not multi';
Don't use COUNT_RECURSIVE
click this site for know why
use rsort and then use isset
function is_multi_array( $arr ) {
rsort( $arr );
return isset( $arr[0] ) && is_array( $arr[0] );
}
//Usage
var_dump( is_multi_array( $some_array ) );
Even this works
is_array(current($array));
If false its a single dimension array if true its a multi dimension array.
current will give you the first element of your array and check if the first element is an array or not by is_array function.
You can also do a simple check like this:
$array = array('yo'=>'dream', 'mydear'=> array('anotherYo'=>'dream'));
$array1 = array('yo'=>'dream', 'mydear'=> 'not_array');
function is_multi_dimensional($array){
$flag = 0;
while(list($k,$value)=each($array)){
if(is_array($value))
$flag = 1;
}
return $flag;
}
echo is_multi_dimensional($array); // returns 1
echo is_multi_dimensional($array1); // returns 0
I think this one is classy (props to another user I don't know his username):
static public function isMulti($array)
{
$result = array_unique(array_map("gettype",$array));
return count($result) == 1 && array_shift($result) == "array";
}
In my case. I stuck in vary strange condition.
1st case = array("data"=> "name");
2nd case = array("data"=> array("name"=>"username","fname"=>"fname"));
But if data has array instead of value then sizeof() or count() function not work for this condition. Then i create custom function to check.
If first index of array have value then it return "only value"
But if index have array instead of value then it return "has array"
I use this way
function is_multi($a) {
foreach ($a as $v) {
if (is_array($v))
{
return "has array";
break;
}
break;
}
return 'only value';
}
Special thanks to Vinko Vrsalovic
Its as simple as
$isMulti = !empty(array_filter($array, function($e) {
return is_array($e);
}));
This function will return int number of array dimensions (stolen from here).
function countdim($array)
{
if (is_array(reset($array)))
$return = countdim(reset($array)) + 1;
else
$return = 1;
return $return;
}
Try as follows
if (count($arrayList) != count($arrayList, COUNT_RECURSIVE))
{
echo 'arrayList is multidimensional';
}else{
echo 'arrayList is no multidimensional';
}
$is_multi_array = array_reduce(array_keys($arr), function ($carry, $key) use ($arr) { return $carry && is_array($arr[$key]); }, true);
Here is a nice one liner. It iterates over every key to check if the value at that key is an array. This will ensure true