Find how many numbers are greater than N in an array - php

If I have an indexed PHP array:
$array = array(2, 12, 23, 34, 36, 36, 36, 56);
And I have a variable:
$number = 30;
How do I calculate the number of "array positions" that are higher than $number?
For example, the function should return 5, because there are 5 numbers (34, 36, 36, 36 and 56) that are higher than 30.
Edit: I've already tried different methods of counting the array values, but I have no idea how to count the positions. It has me stumped.

Can also use
array_reduce — Iteratively reduce the array to a single value using a callback function
Example:
$array = array(2, 12, 23, 34, 36, 36, 36, 56);
$number = 30;
echo array_reduce($array, function($ret, $val) use ($number) {
return $ret += $val > $number;
});
Or hardcode the number into the callback
echo array_reduce($array, function($ret, $val) {
return $ret += $val > 30;
});

As another alternative, use array_filter() to remove the elements from the array that you don't want, then just count() the remaining list...
$array = array(2, 12, 23, 34, 36, 36, 36, 56);
$number = 30;
$gtn = array_filter($array, function($value) use ($number) { return $value > $number; });
echo count($gtn);
$gtn will contain the numbers (34, 36, 36, 36, 56), which may be useful for other things in your code.

You don't need to iterate the full array.
If you first sort the array then as soon as you find a larger number you can break the loop and use the key value from there.
$array = array(2, 12, 23, 34, 36, 36, 36, 56);
Sort($array);
$number = 30;
Foreach($array as $key => $val) If($val >= $number) break;
$larger = array_slice($array, $key);
Echo count($larger) . "\n";
Var_dump($larger);
Output:
5 //echo
array(5) { // var_dump
[0] => 34
[1] => 36
[2] => 36
[3] => 36
[4] => 56
}
https://3v4l.org/8FoOP

You can use array_reduce for this task:
$array = array(2, 12, 23, 34, 36, 36, 36, 56);
$number = 30;
$cnt = array_reduce($array, function ($carry, $item) use ($number) {
if ( $item > $number ) {
$carry++;
}
return $carry;
});
echo $cnt;

Try this code:
function findGreaterNumberCount($array, $number) {
$count = 0;
foreach ($array as $value) {
if ($value > $number) {
$count++;
}
}
return $count;
}
echo findGreaterNumberCount(array(2, 12, 23, 34, 36, 36, 36, 56), 30);
This platform doesn't recommend to write code. So you should try something before asking a question. Be careful next time.

use array reduce and make your code short
$array = [2, 12, 23, 34, 36, 36, 36, 56];
$number = 30;
$totalNumberOfItems = array_reduce($array, function ($sum, $item) use ($number) {
if($item > $number)
$sum++;
return $sum;
});
Var_dump($cnt);

You can iterate array with array_filter to find the greatest array element.
$num = 30;
$array = array(2, 12, 23, 34, 36, 36, 36, 56);
$a = array_filter($array, function($value) use( $num ){
return $num < $value;
});
print_r($a);
Out put
Array
(
[3] => 34
[4] => 36
[5] => 36
[6] => 36
[7] => 56
)

Related

Creating a list and indexing

Given a two list. Create a third list by picking an odd-index element from the first list and even index elements from the second.
For Example:
listOne = [3, 6, 9, 12, 15, 18, 21]
listTwo = [4, 8, 12, 16, 20, 24, 28]
Expected Output:
Printing Final third list
[6, 12, 18, 4, 12, 20, 28]
I think, it will be helpful for you.
<?php
$listOne = [3, 6, 9, 12, 15, 18, 21];
$listTwo = [4, 8, 12, 16, 20, 24, 28];
$NlistOne=[];
$NlistTwo=[];
//odd-index positions from list one [6, 12, 18]
foreach ($listOne as $key => $value) {
if($key%2==1){
array_push($NlistOne, $value);
}
}
//even-index positions from list two [4, 12, 20, 28]
foreach ($listTwo as $key => $value) {
if($key%2==0){
array_push($NlistTwo, $value);
}
}
//Printing Final third list [6, 12, 18, 4, 12, 20, 28]
print_r(array_merge($NlistOne,$NlistTwo));
?>
Output will be:
Array ( [0] => 6 [1] => 12 [2] => 18 [3] => 4 [4] => 12 [5] => 20 [6] => 28 )
//init result array
//loop over listOne, using for($i=1;$i<sizeof($listOne);$i=$i+2)
//and add to result for each iteration, $resultArr[] = $listOne[$i]
//do the same with listTwo, but for($i=*0*
You can merge both of arrays and then pick all odd elements
$listOne = [3, 6, 9, 12, 15, 18, 21];
$listTwo = [4, 8, 12, 16, 20, 24, 28];
$result = [];
foreach ( array_merge($listOne, $listTwo) as $value ){
if ( $key % 2 ) {
$result[] = $value;
}
}
If array length isn't fixed, say it could contain not 7 elements, then you need to check it before merging to make it have odd number of elements
$listOne = [3, 6, 9, 12, 15, 18, 21, 777];
$listTwo = [4, 8, 12, 16, 20, 24, 28];
$result = [];
if ( count($listOne) % 2 !== 1 ) {
$listOne[] = 0;
}
foreach( array_merge($listOne, $listTwo) as $value ){
if ( $key % 2 ) {
$result[] = $value;
}
}
you don't have to loop over whole array array_filter will do this for you, Constant ARRAY_FILTER_USE_KEY will check each key for odd or for even
<?php
$a1 = [3, 6, 9, 12, 15, 18, 21];
$a2 = [4, 8, 12, 16, 20, 24, 28];
function odd($var)
{
// returns whether the input integer is odd
return $var & 1;
}
function even($var)
{
// returns whether the input integer is even
return !($var & 1);
}
$result= (array_merge(array_filter($a1, 'odd', ARRAY_FILTER_USE_KEY),array_filter($a2, 'even', ARRAY_FILTER_USE_KEY)));
output you will get
Array (
[0] => 6
[1] => 12
[2] => 18
[3] => 4
[4] => 12
[5] => 20
[6] => 28 )
Iterate over first one and take only values of odds indices, and loop again through second one and take evens indices.
$listOne = [3, 6, 9, 12, 15, 18, 21];
$listTwo = [4, 8, 12, 16, 20, 24, 28];
$res = [];
for ($i=0; $i < count($listOne); $i++) {
if($i & 1) // $i is odd.
$res[] = $listOne[$i];
}
for ($j=0; $j < count($listTwo); $j++) {
if(n % 2 === 0) // $j is even.
$res[] = $listTwo[$j];
}
Result:
echo "List One :".json_encode($listOne)."<br>";
echo "List Two :".json_encode($listTwo)."<br>";
echo "Lists Merged:".json_encode($res);
Output:*
/*
List One :[3,6,9,12,15,18,21]
List Two :[4,8,12,16,20,24,28]
Lists Merged:[6,12,18,4,12,20,28]
*/
Iterate over arrays:
take odds in array starting with index One and increment it by two.
take evens in array by starting with index Zero and increment it by two.
$listOne = [3, 6, 9, 12, 15, 18, 21]; $listTwo = [4, 8, 12, 16, 20, 24, 28];
$res = [];
for ($i=1; $i < count($listOne); $i+=2) {
$res[] = $listOne[$i];
}
for ($j=0; $j < count($listTwo); $j+=2) {
$res[] = $listTwo[$j];
}
print(json_encode($res)); // [6,12,18,4,12,20,28]

Finding higher and lower numbers in an array and storing in one array

I need to get the closest lowest and highest to a number.
Attempt
<?php
$a = array(1, 8, 23,42,47, 52, 55, 66, 74,75, 76,77,78, 95,);
sort($a);
$v = 58;
$lesser = null;
$greater = null;
foreach($a as $key => $current){
if($current <= $v){
$lesser = $current;
$greater = $a[($key+1)];
}else{
}
}
print_r(array(
"lesser" => $lesser,
"greater" => $greater,
));
?>
/** output :
Array
(
lesser => 55
greater => 66
)
**/
My aim is to get all the numbers greater to the given number, and the same with the lesser:
greater => 66, 74, 75, 77, 78, 95
lesser => 55, 52, 47, 42, 23, 8, 1
How do I solve this problem?
Make $lesser and $greater arrays that you push onto, instead of replacing.
<?php
$a = array(1, 8, 23,42,47, 52, 55, 66, 74,75, 76,77,78, 95,);
$v = 58;
$lesser = [];
$greater = [];
foreach($a as $key => $current){
if ($current < $v) {
$lesser[] = $current;
} elseif ($current > $v) {
$greater[] = $current;
}
}
print_r(array(
"lesser" => $lesser,
"greater" => $greater,
));
?>

For-each loop, larger than 20 into another array

I'm stuck on this exercise that I can't seem to get for the life of me.
$numbers2 = [21, 5, 4, 6, 76, 2, 18, 85, 55, 1];
foreach ($numbers2 as &$value) {
$largeNumbers[] = $value > 20;
}
That's the code I have so far. What I am trying to do here is use a for-each loop to add all the numbers that are larger than 20 into another Array, which I have named $largeNumbers. The code I have inserted above seems to be printing out true and false values, which is not what I was going for. I'd really appreciate it someone could tell me what I'm possibly doing wrong or even show me a better way. I have to use a for-each loop.
For each item, you are checking if it's larger than 20, which results in a boolean value (it either is or is not), and you then store this value to the result array. Instead, you could use an if statement` to only take the elements that answer the condition:
foreach ($numbers2 as &$value) {
if ($value > 20) {
$largeNumbers[] = $value;
}
}
<?php
$nums = [21, 5, 4, 6, 76, 2, 18, 85, 55, 1];
$less_than_or_equal_to_20 = [];
foreach($nums as $v)
if($v <= 20)
$less_than_or_equal_to_20[] = $v;
$out = array_diff($nums, $less_than_or_equal_to_20);
var_export($out);
Output:
array ( 0 => 21, 4 => 76, 7 => 85, 8 => 55, )
<?php
$nums = [21, 5, 4, 6, 76, 2, 18, 85, 55, 1];
foreach([$nums] as $v)
$out = array_filter($v, function($v) {
return $v > 20;
});
var_export($out);
Output:
array ( 0 => 21, 4 => 76, 7 => 85, 8 => 55, )

Best way to check if all array values are in a range

How is best way to check if all array values are in range?
For example:
$range = range(10, 40);
$array1 = array(10, 20, 40); // OK
$array2 = array(11, 22, 42, 30); // FALSE
$array3 = array(50); // OK
$array4 = array(10, 20, 30, 'a'); // FALSE
$array5 = array("%", 20); // FALSE
$array6 = array(10, 20, 40, 39, 40); // OK
So how can I check if array values are numbers (integer) and are in range?
I tried:
$tmp = 0;
foreach ($array1 as $a1) {
if (!in_array($a1, $range) && is_int($a1)) {
$tmp++;
}
}
if ($tmp > 0) {
echo "false";
} else {
echo "ok";
}
Maybe is better way? Maybe with array_map()?
<?php
$range = range(10, 40);
$array1 = array(10, 20, 40);
$isInRange = (min($array1)>=min($range) and max($array1)<=max($range)) ? "Yes" : "No";
echo $isInRange;
//prints 'Yes' when compared with array(10, 20, 40);
//prints 'No' when compared with array(11, 22, 42, 30); as you have out range value 42 here
?>
A simplest way to check this is using max and min here, because you avoid validating for integers here. max selects the maximum value within the array, and min the least one.
Would something like this do the job ?
It compare every value in the array with the range ($min and $max), and return "Not in range" if one of the value in the array is not between the specified range.
$min = 10;
$max = 40;
$array1 = array(10, 20, 40); // OK
foreach ($array1 as $tmpArr){
if (!($min<=$tmpArr && $tmpArr<=$max)){
echo "Not in range";
break;
}
}
just run it and learn fro here.
<?php
$array1 = array(11, 20, 30);
$array2 = array(11, 22, 22, 30);
$array3 = array(20);
$array4 = array("a", 20, 30, 13);
$array5 = array(46, 20);
$array6 = array(52, 20, 31, 39, 30);
$arr = array($array1, $array2, $array3, $array4, $array5, $array6);
array_walk($arr, function($val){
if( min($val) > 10 && max($val) < 40){
echo "<br/>matched for<br/>";
print_r($val);
} else {
echo "<br/>not matched for<br />";
print_r($val);
}
});
?>
There are a lot better way, you can try.
Output
matched for
Array ( [0] => 11 [1] => 20 [2] => 30 )
matched for
Array ( [0] => 11 [1] => 22 [2] => 22 [3] => 30 )
matched for
Array ( [0] => 20 )
not matched for
Array ( [0] => a [1] => 20 [2] => 30 [3] => 13 )
not matched for
Array ( [0] => 46 [1] => 20 )
not matched for
Array ( [0] => 52 [1] => 20 [2] => 31 [3] => 39 [4] => 30 )
function array_values_all_numbers($a, $min = PHP_INT_MIN, $max = PHP_INT_MAX){
foreach($a as $v){
if(is_int($v) && $v >= $min && $v <= $max){
return false;
}
}
return true;
}
var_dump(array_values_all_numbers(range(0, 100, 3))); // true
var_dump(array_values_all_numbers([1, 2, 3, 4, 'a'])); // false
var_dump(array_values_all_numbers([1, 2, 3, 4], 3, 4)); // false
var_dump(array_values_all_numbers([1, 2, 3, 4], 2, 4)); // true
Or perhaps an alternative:
$myarray = array_filter(array_values($input), 'is_int');
foreach($myarray as $value){
// loop over all array values that are numbers and skip the rest.
}
On a side-note; In terms of programming a range can mean a couple of things:
Checking to see if a number is between two numbers.
Range, looping start to end with an optional step.
PHP function range(), returning an array from start to end with an optional step
It makes for a very confusing question.
Here's a fun way:
var_dump(
array_values($array1) == array_filter(array_values(array_intersect($range, $array1)), 'is_int')
);
Compute the intersection between the range and array
Remove non-integers
Compare with the array
Result is true or false
I assumed you have just a normal array not an associative array.
<?php
$a = array(1,2,3);
$b = array(2,3);
$c = array(2,3,4);
function all_in_range(array $needle, array $haystack) {
return array_reduce(
$needle,
function($carry, $item) use ($haystack){
return $carry?in_array($item,$haystack):false;
},
true
);
}
var_dump(all_in_range($b, $a)); // check $b inside $a - true
var_dump(all_in_range($c, $a)); // check $c inside $a - false
results:
bool(true)
bool(false)
=== or something like this ===
function all_in_range(array $needle, $min, $max) {
return ( is_int($min) && is_int($max) ) ?
array_reduce(
$needle,
function($carry, $item) use ($min, $max){
// limits values are included
return $carry?is_int($item)?($item>=$min && $item<=$max):false:false;
},
true
) : 'wrong limits';
}
var_dump(all_in_range($b, 1, 3)); // check $b inside range 1..3
var_dump(all_in_range($c, 1, 3)); // check $c inside range 1..3

Merge two flat arrays and omit values from one array when the other array has more occurrences of the same value

I want to merge every element of two arrays, BUT if a value is in both arrays, then only add the values from the array which has the biggest amount of that element. The result array does not need to be sorted in any special way, but I did it here for readability.
Sample input:
$array1 = [1, 4, 7, 3, 3, 3];
$array2 = [4, 0, 3, 4, 9, 9];
Desired result:
[0, 1, 3, 3, 3, 4, 4, 7, 9, 9]
//a2 a1 a1 a1 a1 a2 a2 a1 a2 a2
Note, this will be used on big arrays, with unknown integer values. Is there a good way to do this that doesn't require too much time/processing power?
Try this:
<?php
$array1 = [1, 4, 7, 3, 3, 3];
$array2 = [4, 0, 3, 4, 9, 9];
function min_merge($arr1, $arr2) {
$arr1 = array_count_values($arr1);
$arr2 = array_count_values($arr2);
foreach ($arr2 as $index => $arr)
if (!isset($arr1[$index]) || $arr > $arr1[$index])
$arr1[$index] = $arr;
foreach ($arr1 as $index => $arr)
for ($i = 0; $i < $arr; $i++)
$final[] = $index;
return $final;
}
print_r(min_merge($array1, $array2));
Output:
Array (
[0] => 1
[1] => 4
[2] => 4
[3] => 7
[4] => 3
[5] => 3
[6] => 3
[7] => 0
[8] => 9
[9] => 9
)
Unsorted, but it contains all the numbers from [0, 1, 3, 3, 3, 4, 4, 7, 9, 9].
$count[0] = array_count_values($arr1);
$count[1] = array_count_values($arr2);
$out = array();
array_map(function($e) use(&$out, $count){
$n1 = (isset($count[0][$e])) ? $count[0][$e] : 0;
$n2 = (isset($count[1][$e])) ? $count[1][$e] : 0;
$next = ($n2 > $n1) ? array_fill(0, $n2, $e) : array_fill(0, $n1, $e);
$out = array_merge($out, $next);
}, array_keys($count[0] + $count[1]));
print_r($out);
My modernized rewrite of #DaveChen's answer using PSR-12 coding standards and eliminating single-use declarations. This approach uses one loop to determine the greater count for numbers shared by both value-count arrays, then a second loop to populate the result array. (Demo)
$counts1 = array_count_values($array1);
foreach (array_count_values($array2) as $number => $count) {
if ($count > ($counts1[$number] ?? 0)) {
$counts1[$number] = $count;
}
}
$result = [];
foreach ($counts1 as $number => $count) {
array_push($result, ...array_fill(0, $count, $number));
}
var_export($result);
My modernized rewrite of #Expedito's answer which does not abuse the array_map() (when array_map()'s return value is not used, use array_walk() for functional style programming), uses a foreach() loop to eliminate variable scope issues, and generally implements D.R.Y. techniques. (Demo)
$counts1 = array_count_values($array1);
$counts2 = array_count_values($array2);
$result = [];
foreach ($counts1 + $counts2 as $num => $cnt) {
array_push(
$result,
...array_fill(
0,
max($counts1[$num] ?? 0, $counts2[$num] ?? 0),
$num
)
);
}
var_export($result);
And I wanted to add a new approach of my own, despite the fact that it may or may not perform better than the other two snippets. The script makes one pass over the first value count arrays to populate a temporary array which demands which numbers from the first array should be represented in the result array. Then it isolates value intersections from the first array, value differences from the second array, then merges them. (Demo)
$counts1 = array_count_values($array1);
$counts2 = array_count_values($array2);
$keepFrom1 = array_keys(
array_filter(
$counts1,
fn($count, $number) => ($counts2[$number] ?? 0) <= $count,
ARRAY_FILTER_USE_BOTH
)
);
var_export(
array_merge(
array_intersect($array1, $keepFrom1),
array_diff($array2, $keepFrom1)
)
);
probably not the most optimized but
<?php
$one=[1, 4, 7, 3, 3, 3];
$two=[4, 0, 3, 4, 9, 9];
sort($one);
sort($two);
foreach($one as $el)
{
$combined[]=$el;
if (array_search($el,$two))
{
unset($two[array_search($el,$two)]);
}
}
foreach($two as $el)
{
$combined[]=$el;
}
sort($combined);
print_r($combined);
?>

Categories