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

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

Related

PHP array_unique is not returning unique values [duplicate]

My array is :
$array= array(4,3,4,3,1,2,1);
And I'd like to output it like below:
Output = 2
(As 2 is present only once)
This is what I've tried:
$array = array(4, 3, 4, 3, 1, 2, 1);
$array1 = array(4, 3, 4, 3, 1, 2, 1);
$array_diff = array_diff($array, $array1);
*Read last section of this an for the most stable technique the avoids fringe case issues -- it is also the most verbose.
One-liner with no loops: (Demo)
var_export(array_keys(array_intersect(array_count_values($array),[1])));
The breakdown:
array_keys( // return the remaining keys from array_count_values
array_intersect( // filter the first array by second
array_count_values($array), // count number of occurrences of each value
[1] // identify the number of occurrences to keep
)
)
if you (or any future reader) wants to keep more values, replace the second parameter/array in array_intersect().
for instance:
you want to keep 1,2,and 3: array(1,2,3) or [1,2,3]
p.s. For the record, you can use array_filter() with a custom function to omit all non-1 count values, but I have used array_intersect() because the syntax is more brief and IMO easier to read.
p.s. thought I'd revisit and include a PHP7.4 technique and compare against other function-based techniques...
Code: (Demo)
$numbers = [4, 3, 4, 3, 1, 2, 1];
var_export(
array_keys(
array_intersect(
array_count_values($numbers),
[1]
)
)
);
echo "\n---\n";
var_export(
array_keys(
array_filter(
array_count_values($numbers),
function($count) {
return $count === 1;
}
)
)
);
echo "\n---\n";
// PHP7.4+
var_export(
array_keys(
array_filter(
array_count_values($numbers),
fn($count) => $count === 1
)
)
);
*For similar tasks which have values which are not guaranteed to be integers, array_count_values() will complain with "Warning: array_count_values(): Can only count string and integer values".
Even a classic loop that uses values as first level keys like #LF00's answer will suffer potential side effects due to floats and numeric values being cast as integers automatically.
This means that a more general-use solution would be: (Demo)
$result = [];
foreach ($array as $index => $value) {
foreach ($array as $i => $v) {
if ($value === $v && $index !== $i) {
continue 2; // duplicate found, stop checking this value; do not retain
}
}
$result[] = $value;
}
var_export($result);
You could use the array_count_values() php function.
For example:
$numbers = [4, 3, 4, 3, 1, 2, 1];
// build count array as key = number and value = count
$counter_numbers = array_count_values($numbers);
print_r($counter_numbers);
Output :
Array
(
[4] => 2
[3] => 2
[1] => 2
[2] => 1
)
Then loop through the new array to get non-repeated values :
$unique_numbers = [];
foreach ($counter_numbers as $number => $count) {
if ($count === 1) {
$unique_numbers[] = $number;
}
}
print_r($unique_numbers);
Output :
Array
(
[0] => 2
)
You can do it like this: Count the occurrences of each element, then filter out the occurrences bigger than 1.
$array = [4, 3, 4, 3, 1, 2, 1];
foreach ($array as $v)
{
$arr[$v][] = 1; // doesn't matter if 1 is set to a different value
}
foreach($arr as $k => $v)
{
if (count($v) == 1) {
$o[] = $k;
}
}
print_r($o);
result:
Array
(
[0] => 2
)
If in your scenario there will be only one unique value you could use:
$array= array(4,3,4,3,1,2,1);
$singleValue = array_search(1, array_count_values($array));
var_dump($singleValue) // Outputs: 2

Find how many numbers are greater than N in an array

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
)

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);
?>

PHP Array Combine and Sum

I have multiple arrays, that get generated when a for loop completes. Now I need to get the total of all these arrays together, but in order, for instance:
array1(2, 4, 6, 8, 10)
array2(2, 4, 6, 8, 10)
I need to add the 2's together, the 4's etc etc
Then put them into another array.
Some combination of array_combine and array_sum seems to be the solution but I can't figure it out.
Any help is greatly appreciated.
You could do this without any php function except count,
$limit = count($array1);
for ($i = 0; $i < $limit; $i++) {
$array_res[$i] = $array1[$i] + $array2[$i];
should work. This will combine your two arrays and add them in the same order. But be sure you used sort or ksort on both of your arrays before if you're not sure they are in the same order.
1st stlye
$a1 = array(
"a" => 2
,"b" => 0
,"c" => 5
);
$a2 = array(
"a" => 3
,"b" => 9
,"c" => 7
,"d" => 10
);
$a3 = array_merge($a1, $a2);
print_r($a3);
2nd style
$a3 = $a1;
foreach($a2 as $k=>$v) {
if(array_key_exists($k,$a3))
$a3[$k] + = $v;
else
$a3[$k] = $v;
}
You should use array_map():
$arr1 = array(2, 4, 6, 8, 10);
$arr2 = array(1, 2, 3, 4, 5);
$arr3 = array_map(
function($foo, $bar){
return $foo+$bar;
},
$arr1, $arr2
);
print_r($arr3); // outputs:
Array
(
[0] => 3
[1] => 6
[2] => 9
[3] => 12
[4] => 15
)
You can do something like this
$a = array(2, 4, 6, 8, 10);
$b = array(2, 4, 6, 8, 10);
$c = array_map("test", $a, $b);
function test($a, $b) {
return $a + $b;
}
print_r($c);
As far as I understand your question You want sum of all the similar digits in both the array:
<?php
$array1= array(2, 4, 6, 8, 10);
$array2=array(2, 4, 6, 8, 10);
$array_sum=array();
foreach($array1 as $key1=>$val1)
{
$sum=0;
foreach($array2 as $key2 => $val2)
{
if($val1==$val2)
{
$sum=$sum+$val1;
}
}
$array_sum[]=$sum;
}
print_r($array_sum);
?>

Sorting an array of arrays by the child array's length?

What's the best way in PHP to sort an array of arrays based on array length?
e.g.
$parent[0] = array(0, 0, 0);
$parent[2] = array("foo", "bar", "b", "a", "z");
$parent[1] = array(4, 2);
$sorted = sort_by_length($parent)
$sorted[0] = array(4, 2);
$sorted[1] = array(0, 0, 0);
$sorted[2] = array("foo", "bar", "b", "a", "z");
This will work:
function sort_by_length($arrays) {
$lengths = array_map('count', $arrays);
asort($lengths);
$return = array();
foreach(array_keys($lengths) as $k)
$return[$k] = $arrays[$k];
return $return;
}
Note that this function will preserve the numerical keys. If you want to reset the keys, wrap it in a call to array_values().
I'm upvoting Peter's but here's another way, I think:
function cmp($a1, $a2) {
if (count($a1) == count($a2)) {
return 0;
}
return (count($a1) < count($a2)) ? -1 : 1;
}
usort($array, "cmp");
Try the usort function:
function sortByLength( $arr1, $arr2 )
{
$c1 = count($arr1);
$c2 = count($arr2);
return $c1 < $c2 ? -1 : $c1 == $c2 ? 0 : 1;
}
usort($initial_array,'sortByLength');
edited to respect parameters-by-reference; it's the same answer as #david, anyway
sort() compares by size before quality.
Because all of your rows have the same flat structure, sort() will sort ascending by row size, sort ascending by first elements, then the next elements, etc.
Code: (Demo)
$parent[0] = array(0, 0, 0);
$parent[2] = array("foo", "bar", "b", "a", "z");
$parent[1] = array(4, 2);
$parent[5] = array(11, 2);
$parent[3] = array(1, 21);
$parent[4] = array(11, 1);
sort($parent);
var_export($parent);
Output:
array (
0 =>
array (
0 => 1,
1 => 21,
),
1 =>
array (
0 => 4,
1 => 2,
),
2 =>
array (
0 => 11,
1 => 1,
),
3 =>
array (
0 => 11,
1 => 2,
),
4 =>
array (
0 => 0,
1 => 0,
2 => 0,
),
5 =>
array (
0 => 'foo',
1 => 'bar',
2 => 'b',
3 => 'a',
4 => 'z',
),
)
This performs identically to this use of array_multisort() with iterated calls of count: (Demo)
array_multisort(array_map('count', $parent), $parent);
var_export($parent);
Using usort() is different if only sorting on the counts because in modern PHP it will leave tied comparisons in their original position : (Demo)
usort($parent, fn($a, $b) => count($a) <=> count($b));
var_export($parent);

Categories