I have an array that has been sorted from low to high which has over 260k values in. I have found out the mean(average) and median of the array just need to find out the mode?
I cannot use any mathematical functions that PHP has, it has to be all done manually.
I would like it so there could be just one value that is the mode but then there can be multiple values that can be the mode. I also need to be able to record the number of times that the value is stored. For example the number 51 appears 6 times so I can print both values.
This is my code so far:
$amountRecords = 0;
$totalValue = 0;
$valueArray = array();
// reads in csv file
$handle = fopen('Task1-DataForMeanMedianMode.csv', 'r');
// to skip the header names/values
fgetcsv($handle);
// creates array containing variables of csv file in ascending order
while(($row = fgetcsv($handle, "\r")) != FALSE)
{
// if amountRecords equals 0
if($amountRecords == 0)
{
// adds value from csv to array
$valueArray[] = $row[1];
} // else amountRecords does not equal 0
else
{
// if the value in array location before is greater than the current value from the csv file
if($valueArray[$amountRecords - 1] > $row[1])
{
// the current array location becomes the one in the location before
$valueArray[] = $valueArray[$amountRecords - 1];
// add the value from the csv to the location before
$valueArray[$amountRecords - 1] = $row[1];
} // if the value in the location before is not greater than the current value in the csv file
else
{
// adds value from csv to array
$valueArray[] = $row[1];
}
}
// calculates the total value of the values in csv file
$totalValue = $totalValue + $row[1];
// calculates the number of values in the csv file
$amountRecords++;
}
// calculate average value of payments
$averageValue = $totalValue / $amountRecords;
// limit integer to 2 decimal place
$average = number_format($averageValue,2,'.','');
// finds middle value
$middle = floor(($amountRecords / 2) - 1);
// calculates the median value
// if array size is even
if($amountRecords % 2 == 0)
{
// calculates median
$median = $valueArray[$middle];
}
else // if array size is odd
{
// calculate low and high values
$low = $valueArray[$middle];
$high = $valueArray[$middle + 1];
// calculates median
$median = (($low + $high) / 2);
}
// works out mode
// creates array count
$count = array();
// for each value in the valueArray
foreach( $valueArray as $value )
{
if( isset( $count[$value] ))
{
$count[$value]++;
}
else
{
$count[$value] = 1;
}
}
$mostCommon = "";
$iter = 0;
foreach( $count as $k => $v )
{
if( $v > $iter )
{
$mostCommon = $k;
$iter = $v;
}
}
$modeArray = array( "mode" => $mostCommon , "count" => $iter );
The mode of a numerical set is the number that occurs the most often. You can do this with PHP using code similar to the following:
$values = array_count_values($valueArray);
$mode = array_search(max($values), $values);
Simple!
$arr = array(4,6,7,1,4,7,4,7,1);
$freq = array();
for($i=0; $i<count($arr); $i++)
{
if(isset($freq[$arr[$i]])==false)
{
$freq[$arr[$i]] = 1;
}
else
{
$freq[$arr[$i]]++;
}
}
$maxs = array_keys($freq, max($freq));
for($i=0; $i<count($maxs); $i++)
{
echo $maxs[$i] . ' ' . $freq[$maxs[$i]];
echo '<br />';
}
Mathematical only solution:
//sample data
$dataArr = ["1", "3", "5", "1", "3", "7", "1", "8", "1"];
//a multidimensional array to hold the keys (extracted fro above) and their values (number of occurrences)
$multiDArr = [];
for ($i = 0; $i < count($dataArr); $i++) {
$key = $dataArr[$i];
if (isset($multiDArr[$key])) {
//key already exists; increment count of its value
$multiDArr[$key] = $multiDArr[$key] + 1;
} else {
//key does nto exist; add it and an inital value of 1
$multiDArr[$key] = 1;
}
}
$highestOccuring = 0;
$highestOccuringKey = null;
foreach ($multiDArr as $key => $value) {
if ($value > $highestOccuring) {
$highestOccuring = $value;
$highestOccuringKey = $key;
}
}
echo "MODE / highest occuring key: " . $highestOccuringKey;
/** find array mode, most often see value
* #param list(int) $a_in
* #return list(int)
*/
function array_mode(array $a_in): array{
$a_freq = [];
foreach( $a_in as $v ) {
if (!isset($a_freq[$v])) {
$a_freq[$v] = 0;
}
$a_freq[$v]++;
}
$a_maxs = array_keys($a_freq, max($a_freq));
return $a_maxs;
}
// test code
$a_in = [4,6,7,1,4,7,4,7,1];
array_mode( $a_in);
This will take values and turn it into an array of the modes. For Example: print_r(get_mode(1,2,2,3,3,3,4,4,5,5,5,6,7,8,9)); will return,
Array
(
[0] => Array
(
[value] => 3
[count] => 3
)
[1] => Array
(
[value] => 5
[count] => 3
)
)
code:
function get_mode(...$inputArray){
$max=0;
return array_reduce(
array_values(array_reduce(array_values($inputArray),function($talliedArray,$inputNode){
if(isset($talliedArray[(string)$inputNode]))
$talliedArray[(string)$inputNode]['count']++;
else
$talliedArray[(string)$inputNode] = [
'value' => $inputNode,
'count' => 1
];
return $talliedArray;
},[])),function($modeArray,$talliedNode)use(&$max){
if($talliedNode['count'] < $max) return $modeArray;
if($talliedNode['count']=== $max) return array_merge($modeArray,[$talliedNode]);
//if count > $max
$max = $talliedNode['count'];
return [$talliedNode];
},[]);
}
This satisfies the "no math functions", the "multiple return modes" and the "have the value and number of occurrences returned".
This will only really work with strings and numbers. It will go weird with booleans, Objects and Arrays.
Related
I have two arrays, one of values, and the other for ranges:
$ranges = array(10,15,30);
$values = array(1,4,12,15,27,32);
I want to count the number of values in between each ranges, as such:
$output = array(
"<10" => 2, // number of values < 10
"10-15" => 1, // number of values >= 10 && < 15
"15-30" => 2, // number of values >= 15 && < 30
">=30" => 1, // number of values > 30
);
Obviously, ranges and values are dynamic and can't be hard-coded if-conditions.
What I made so far is working:
$output = array();
foreach ( $values as $val ) {
foreach ( $ranges as $k => $range ) {
if ( $k == 0 ) { // first range
$max = $range;
$label = '<' . $max;
if ( $val < $max ) {
$output[$label] += 1;
}
} else if ( $k == count($ranges) - 1 ) { // last range
$min = $ranges[$k-1];
$max = $range;
$label = $min . '-' . $max;
if ( $val >= $min && $val < $max ) {
$output[$label] += 1;
}
$min = $range;
$label = '>=' . $min;
if ( $val >= $min ) {
$output[$label] += 1;
}
} else {
$min = $ranges[$k-1];
$max = $range;
$label = $min . '-' . $max;
if ( $val >= $min && $val < $max ) {
$output[$label] += 1;
}
}
}
}
print_r($output);
This seems costly and I'm really not sure about it. Is there a simpler way to achieve what I'm looking for?
You can simplify the logic a bit by added limiting values to the beginning and end of the $ranges array and then just processing the whole array by pairs.
<?php
$ranges = [10,15,30];
$values = [1,4,12,15,27,32];
\array_push($ranges, null); // append null to array
\array_unshift($ranges, null); // prepend null to array
$output = [];
$count = \count($ranges);
for ($i = 0; $i < $count - 1; $i++) {
$output[] = ['start' => $ranges[$i], 'end' => $ranges[$i+1], 'count' => 0];
}
foreach ($values as $value) {
foreach ($output as $key => $range) {
if (
($range['start'] === null || $range['start'] <= $value) &&
($range['end'] === null || $range['end'] > $value)
) {
$output[$key]['count']++;
break;
}
}
}
var_dump($output);
This starts off by creating a zeroed array with the keys from the $ranges array (using array_fill_keys()), plus one for the values 'over' the last entry.
The loops over each value and checks it against the range, if it finds it, it just adds 1 to the corresponding count and stops looking. If after finishing the loop, the value is greater than the last range, it adds 1 to the 'over' entry.
$ranges = array(10,15,30);
$values = array(1,4,12,15,27,32);
$rangeCount = array_fill_keys($ranges, 0);
$rangeCount[ "over" ] = 0;
foreach ( $values as $value ) {
foreach ( $ranges as $range ) {
if ( $value < $range ) {
$rangeCount [ $range ]++;
break;
}
}
if ( $value >= $range ) {
$rangeCount[ "over" ]++;
}
}
print_r($rangeCount);
which gives...
Array
(
[10] => 2
[15] => 1
[30] => 2
[over] => 1
)
Just to add an optimised version which only does one loop. But assumes the values are in ascending order. Each time it passes the 'current' range it moves onto the next output counter and the last part doesn't even loop for the over the top value, it subtracts the current count from the total count and does a break...
$currentRange = 0;
$numberValues = count($values);
$numberRanges = count($ranges);
$rangeCount = array_fill(0, $numberRanges, 0);
$rangeCount[ "over" ] = 0;
foreach ( $values as $count => $value ) {
if ( $value >= $ranges[$currentRange] ) {
$currentRange++;
if ( $currentRange >= $numberRanges ) {
$rangeCount[ "over" ] = $numberValues - $count;
break;
}
}
$rangeCount[$currentRange]++;
}
print_r($rangeCount);
The following solution first sorts the ranges in ascending/non-decreasing order.
Then, we create a range_map which is a collection of all possible ranges from $ranges.
Then, we loop over all values in $values and do a binary search over $ranges to get the exact range index a particular value belongs to. In the below code, exact index is stored in $low.
Then, we just collect the count by taking the range key from $range_map and incrementing it's counter by 1.
This is faster from nested looping since time complexity of nested looping is O(m*n) where m is size of $ranges and n is size of $values, whereas time complexity of current solution is O(m logm) + O(n logm) where m is size of $ranges and n is size of $values.
Snippet:
<?php
$ranges = array(10,15,30);
$values = array(1,4,12,15,27,32);
sort($ranges);
$range_map = [];
$ptr = 0;
foreach($ranges as $index => $value){
if($index === 0) $range_map[$ptr++] = "<" . $value;
if($index > 0) $range_map[$ptr++] = $ranges[$index - 1] . "-" . $value;
if($index === count($ranges) - 1) $range_map[$ptr++] = ">=" . $value;
}
$result = [];
foreach($values as $value){
$low = 0; $high = count($ranges) - 1;
while($low <= $high){
$mid = $low + intval(($high - $low) / 2);
if($value === $ranges[ $mid ]){
$low = $mid + 1;
break;
}else if($value < $ranges[ $mid ]){
$high = $mid - 1;
}else{
$low = $mid + 1;
}
}
if(!isset($result[$range_map[$low]])) $result[$range_map[$low]] = 0; // get the range key from range_map
$result[$range_map[$low]]++; // increment the value for that range
}
print_r($result);
Demo: https://3v4l.org/JcYBv
Assuming you have pre-sorted ranges and values.
<?php
$ranges = array(10,15,30);
$values = array(1,4,12,15,27,32);
$lower = null;
$i = 0;
$upper = $ranges[$i];
foreach($values as $item) {
if(!is_null($upper) && $item >= $upper) {
$lower = $upper;
$upper = $ranges[++$i] ?? null;
}
$result["$lower<$upper"][] = $item;
}
var_export(array_map('count', $result));
Output:
array (
'<10' => 2,
'10<15' => 1,
'15<30' => 2,
'30<' => 1,
)
I have array with variables from $qA01_1 up to $qA30_5 (150 variables). Some of the variables can have value 0 or 1 or 5 (example $qA21_3 = 0 or 1 or 5). And I would like to know how to make sum of all variables which have value 1.
Here part of array
$qA01_1 = $_SESSION['qA01_1']; // example: $qA01_01 can have value 0 or 1 or 5, like other variables
$qA01_2 = $_SESSION['qA01_2']; // $qA01_02 = 0 or 1 or 5
$qA01_3 = $_SESSION['qA01_3']; // $qA01_03 = 0 or 1 or 5
$qA01_4 = $_SESSION['qA01_4']; // $qA01_04 = 0 or 1 or 5
$qA01_5 = $_SESSION['qA01_5']; // $qA01_05 = 0 or 1 or 5
$qA02_1 = $_SESSION['qA02_1']; // $qA02_01 = 0 or 1 or 5
$qA02_2 = $_SESSION['qA02_2']; // $qA02_02 = 0 or 1 or 5
$qA02_3 = $_SESSION['qA02_3']; // $qA02_03 = 0 or 1 or 5
$qA02_4 = $_SESSION['qA02_4']; // $qA02_04 = 0 or 1 or 5
$qA02_5 = $_SESSION['qA02_5']; // $qA02_05 = 0 or 1 or 5
// up to...
$qA30_1 = $_SESSION['qA30_1']; // $qA30_01 = 0 or 1 or 5
$qA30_2 = $_SESSION['qA30_2']; // $qA30_02 = 0 or 1 or 5
$qA30_3 = $_SESSION['qA30_3']; // $qA30_03 = 0 or 1 or 5
$qA30_4 = $_SESSION['qA30_4']; // $qA30_04 = 0 or 1 or 5
$qA30_5 = $_SESSION['qA30_5']; // $qA30_05 = 0 or 1 or 5
Here is proposal but not work. I´m begginer, please for help.
$values = [];
for($i=1;$i<=30;$i++)
{
foreach([1,2,3,4,5] as $index)
{
if(${'qA'.str_pad($i, 2, "0", STR_PAD_LEFT).'_'.$index} == 1)
{
$values[] = ${'qA'.str_pad($i, 2, "0", STR_PAD_LEFT).'_'.$index};
}
}
}
echo $values;
Just loop through the $_SESSION array:
// This is where we'll hold all the saved numbers
// from values ending with _1
$array_of_numbers = [];
// Loop through each session
foreach ( $_SESSION as $key => $val )
{
// Only save the keys that match and equal 1
if ( preg_match('/^qA\d{2}?_\d$/', $key, $matches) && $val == 1 )
{
$array_of_numbers[] = $val;
}
}
// Sum the numbers that we gathered
$sum_of_array = array_sum($array_of_numbers);
If you just want a sum, you don't need the $values array. Just add the value to a $sum variable.
$sum = 0;
for($i=1;$i<=30;$i++)
{
foreach([1,2,3,4,5] as $index)
{
$var = 'qA'.str_pad($i, 2, "0", STR_PAD_LEFT).'_'.$index
if(${$var} == 1)
{
$sum += ${$var};
}
}
}
echo $sum;
BTW, you can't echo an array. If you want to see the contents of an array, use var_dump($values); or print_r($values);
Time for a rethink. No reason to unpack the array like you are doing.
Lets put the $_SESSION values that we are interested in into a new array and work with that. (not necessary to put in to a new array, I just prefer to not work with the super global variables more than necessary)
//Create new array
$myArray = [];
foreach( $_SESSION as $key=>$val ){
if( preg_match('/qA\d{2}_[1-5]/', $key) ){
$myArray[$key] = $val;
}
}
$sum = 0;
foreach( $myArray as $key=>$val ){
if( preg_match('/qA\d{2}_1/', $key) ){
$sum += $val;
}
}
var_dump($sum);
Since the logic here is a bit confusing, I think separating it out into a couple "self-documenting" functions would be better practice. Something like this should work:
$sum = 0;
for ($i = 1; $i <= 30; $i++) {
for ($j = 1; $j <= 5; $j++) {
$qa_index = qa_index($i, $j);
if ($_SESSION[$qa_index] == 1)
$sum++; // no need to _actually_ sum since it's just 1
}
}
function qa_index($major, $minor) {
return 'qA'.left_pad_zeros($major).'_'.$minor."\n";
}
function left_pad_zeros($val, $pad_amount = 2) {
return str_pad($val, $pad_amount, '0', STR_PAD_LEFT);
}
EDIT: I imagine some people might think functions are unnecessary overhead here. And that may be IF whatever application is using this NEEDS to squeeze out every little bit of performance improvement they can. However, if that's not the case, I think this is much better practice as it is much easier to read and maintain.
$TotalVal = 0;
for($i=1; $i<=5; $i++){
for($j=1; $j<=5; $j++){
If($i<10){
$StrVar = 'qA0'.$j.'_'.$i.'[0]'; // considering ur using array if not remove [0].
If ($$StrVar == 1)
$TotalVal = $TotalVal + $$StrVar;
}else{
$StrVar = 'qA'.$j.'_'.$i.'[0]';
If ($$StrVar == 1)
$TotalVal = $TotalVal + $$StrVar;
}
}
}
echo $TotalVal;
This will give you sum of all values which is having 1 if u need 5 change in if condition
How can I create functions that answer to:
How many different numbers were generated during simulation?
% Of appearance of the numbers from 0 to 50 ?
What is the number that appeared several times during the simulation?
function randomDigits($numDigits) {
$arrayRange = 1000;
if ($numDigits <= 0) {
return '';
} else{
for($i=0; $i<$arrayRange; $i++){
echo mt_rand(0, 50) ." ";
}
}
}
$maxq = 100;
for ($i = 1; $i <= $maxq; $i++) {
echo $i . "<br>\n";
randomDigits($i) . "<br>\n----<br>\n";
}
If you store all the generated numbers into an array, you could use array_count_values()
This will count the occurrences of multiple key values in your array (e.g. if there are 12 occurrences of the number 7) and return the result in an array. This will only work for strings and integer values.
<?php
$array = ['a', 'a', 'a', 'a', 'b', 'b', 'c'];
print_r(array_count_values($array));
?>
Results from the above:
Array(
[a] => 4
[b] => 2
[c] => 1
)
From there, you should be able to easily do all the methods and outputs that you wish.
Here is the basic integration with your existing code...
<?php
$maxq = 100;
$returned_array = [];
for ($i = 1; $i <= $maxq; $i++) {
$returned_array = randomDigits($i); // return the generated array
// merge 'add' the two arrays, like saying i = i +2 or
// merged_array = merged_array + array
array_merge($returned_array, $returned_array);
// here you now have one array of 1000 random values
// print_r($returned_array);
// lets do some math
print_r(array_count_values($returned_array));
// this will show how many values were duplicates...
// e.g
// Array (
// [43] => 25 the number 43 was generated 25 times
// [25] => 22 the number 25 was generated 22 times
// [1] => 28 ect...
// you can loop through this array here and see which value was generated several times,
// format the results nicely, and do all sorts of maths on it as you wish
}
function randomDigits($numDigits) {
$arrayRange = 1000;
$generated_array = []; // here is an actual array that will store the generated numbers
if ($numDigits <= 0) {
return null;
} else {
for($i = 0; $i < $arrayRange; $i++) {
$random = mt_rand(0, 50);
array_push($generated_array, $random); // add the random value to the array
}
// here you have your array of generated numbers
return $generated_array;
}
}
?>
Example here - http://codepad.org/9Dv1CwR7
Sequence generation contains random integers for given length
function generate_array($count, $min, $max) {
$arr = array();
for ($i=0; $i<$count; $i++) {
$arr[$i] = rand($min, $max);
}
return $arr;
}
Calculating percentage of given interval (with a helper function):
function cnt($element, $arr){
$cnt = array_count_values($arr);
return $cnt[$element];
}
function percentages($min, $max, $arr) {
$total = sizeof($arr);
$occurences = 0;
while ($min < $max) {
if (!array_key_exists($min, $arr)) {
continue;
} else {
$occurences = $occurences + cnt($min, $arr);
}
$min++;
}
return $occurences/$total;
}
Add all simulated values to an array, and use array_count_values to get all unique values.
function randomDigits($numDigits) {
$arrayRange = 1000;
if ($numDigits <= 0) {
return '';
} else{
$arr=array();
for($i=0; $i<$arrayRange; $i++){
$val=mt_rand(0, 50);
$arr[]=$val;
echo $val ." ";
}
echo "\n";
$arr=array_count_values($arr);
echo "Total Unique numbers:".count($arr);
}
}
$maxq = 100;
for ($i = 1; $i <= $maxq; $i++) {
randomDigits($i) . "<br>\n----<br>\n";
}
I have a php array with zipcodes returned from a db query. Zip Codes are in German format so 5 digit long.
Example:
array ('90475', '90419', '90425', '90415', '90429', '90479', '90485');
I would like to consolidate the values to "ranges" with placeholder, like:
array ('90...', '904..', '9041.', '9042', '9047.');
//90485 is left out because there is only 1 match.
Edit / logic:
This is for an autosuggestion search. Trying to build a tree so users can search for entries that match any zipcode starting with 90 or 904, etc.. For the autocomplete to make sense I only want to provide the "9041." value if there is a minimum of two entries matching (90419 and 90415 in example). The zipcodes are always 5 digit long from 00000 - 99999.
Highly appreciate any help.
Thanks.
Here you are:
$length = 5;
$zip = array('90475', '90419', '90425', '90415', '90429', '90479', '90485');
$result = array();
for ($i = 2; $i <= $length - 1; $i++) {
$pass = array();
foreach ($zip as $val) {
$pass[substr($val, 0, $i)]++;
}
foreach ($pass as $key => $val) {
if ($val > 1) {
$result[] = $key.str_repeat('.', $length - $i);
}
}
}
sort($result);
var_dump($result);
This will return in $result an array:
array ('90...', '904..', '9041.', '9042', '9047.');
Every range, which is used only once will be ignored and not returned in $result array.
$myArray = array ('90475', '90419', '90425', '90415', '90429', '90479', '90485');
$consolidate = array();
foreach($myArray as $zip) {
for ($c = 2; $c < 5; ++$c) {
$key = substr($zip, 0, $c) . str_repeat('.',5 - $c);
$consolidate[$key] = (isset($consolidate[$key])) ? $consolidate[$key] + 1 : 1;
}
}
$consolidate = array_filter(
$consolidate,
function ($value) {
return $value > 1;
}
);
var_dump($consolidate);
I would like to find the second highest variable in an array.
For example if I have:
$cookies = array(
"chocolate" => "20",
"vanilla" => "14",
"strawberry" => "18",
"raspberry" => "19",
"bluebery" => "29"
);
I can use max($cookies) to find the highest variable, which is "bluebery" => "29".
But how do I find the second highest? "chocolate" => "20"
Sort it and get the second item is the easiest way:
arsort($cookies);
$keys = array_keys($cookies);
echo $keys[1]; // chocolate
echo $cookies[$keys[1]]; // 20
If you want a more efficient way, you can also do it manually, by keeping track of both the highest and second-highest items at the same time:
function secondMax($arr) {
$max = $second = 0;
$maxKey = $secondKey = null;
foreach($arr as $key => $value) {
if($value > $max) {
$second = $max;
$secondKey = $maxKey;
$max = $value;
$maxKey = $key;
} elseif($value > $second) {
$second = $value;
$secondKey = $key;
}
}
return array($secondKey, $second);
}
Usage:
$second = secondMax($cookies);
echo "{$second[0]} => {$second[1]}"; // chocolate => 20
For fun you could use max() twice :)
For example:
Duplicate the array
Run max()
Remove the max
Run max() again
The alternative would to sort the array based on values and get the second element of the array. I'd be curious which is faster. Likely the sort.
arsort($cookies) AND array_shift($cookies) AND list($k, $v) = each($cookies);
echo "$k => $v"; // chocolate => 20
rsort($cookies);
echo $cookies[1];
Try :
asort($cookies);
end($cookies);
prev($cookies);
list($key,$value) = each($cookies);
or reverse it
arsort($cookies);
reset($cookies);
next($cookies);
list($key,$value) = each($cookies);
** Edit **
I thought I'd share this anyway, if someone would stumble across this and need it :
/**
* Returns the key => value pair with the specific rank.
* if $rank is 0, falase is returned. If $rank is positive,
* then the $rank th smallest pair is returned. If $rank
* is negative, then the $rank th biggest pair is returned.
* If $rank range is outside the size of the array, false
* is returned. If a callable function is provided, it will
* be used to sort the data. If $keySort is true, then the
* data will be sorted by keys instead (the callback functions
* will receive the keys to compare instead of values)
*
* #param $data array
* #param $rank int
* #param $cmd_function callable (optional)
* #param $keySort boolean (optional)
* #return array the key => value pair or false
*/
function findByRank($data, $rank, $cmd_function = null, $keySort = false) {
if (($rank == 0) || (abs($rank) > count($data))) {
return false;
}
$sort = ($keySort?'k':'a').'sort';
if ($cmd_function != null) {
$sort = 'u'.$sort;
$sort($data, $cmd_function);
} else {
$sort($data);
}
if ($rank > 0) {
reset($data);
$next = 'next';
} else {
end($data);
$next = 'prev';
$rank = abs($rank);
}
while (--$rank > 0) $next($data);
return each($data);
}
$cookies = array(
"chocolate" => "20",
"vanilla" => "14",
"strawberry" => "18",
"raspberry" => "19",
"bluebery" => "29"
);
header('Content-type:text/plain; charset=utf-8');
var_dump(findByRank($cookies, -10)); // -> false
var_dump(findByRank($cookies, -2)); // -> 'chocolate' key=>value pair
var_dump(findByRank($cookies, -1)); // -> 'blueberry' key=>value pair
var_dump(findByRank($cookies, 0)); // -> false
var_dump(findByRank($cookies, 1)); // -> 'vanilla' key=>value pair
var_dump(findByRank($cookies, 3)); // -> 'raspberry' key=>value pair
Sort the array descending and take the second value. Or, to be save, take the first value and go through the array until you find a smaller one.
function second_largest($arr)
{
sort($arr, SORT_NUMERIC);
return($arr[count($arr) - 2]);
}
//echo 3
echo second_largest(array(0, 3, 4, 1, 2));
Check this URL
http://maheshbokkisam.blogspot.in/2013/04/find-nth-highest-value-in-array-without.html
Find Nth/ N th highest value from given array without using any sorting in PHP
$ar = array(23,56,87,12,98,85,24,54,99,100,1,4,5,2,76,37,92);
$n = count($ar) - 5;
for($i = 0; $i < $n; $i++){
// Get the max value from array // get the Nth value from last loop
echo $a = max($ar);
echo "<br /><pre>"; print_r($ar);
$ar = array_flip($ar); // Flip the array
//print_r($ar);
unset($ar[$a]); // Unset the max value from array
//print_r($ar);
$ar = array_flip($ar); // Flip the array
echo "</pre>";
echo "<hr />";
}
<?php
// Finding Second highest number (In case of index of array is random)
$arr = [-5 => 33, -4 => -2, 8 => 0, 44, 44, 44, 44, 44];
$max = -INF;
$secondMax = -INF;
$size = sizeof($arr);
if ($size > 1) {
foreach ($arr as $key => $value) {
echo "KEY-> ", $key, "VALUE->", $value, "\n";
if ($value > $max) {
$max = $value;
} else {
if ($value < $max && $value > $secondMax) {
$secondMax = $value;
}
}
}
} else if ($size == 0) {
$max = "No Max element";
$secondMax = "No Second highest element";
} else {
foreach ($arr as $key => $value) {
$max = $arr[$key];
$secondMax = "No second highest element";
}
}
echo "maxvalue = ", $max, "\n";
echo "secondmax =", $secondMax;