I have an array and I want to find out if there is at least one false value in it. I was thinking of creating an array_and() function, that just performs a logical AND on all the elements. It would return true if all values are true, otherwise false. Am I over-engineering?
Why dont you just use
in_array — Checks if a value exists in an array
Example:
// creates an array with 10 booleans having the value true.
$array = array_fill(0, 10, TRUE);
// checking if it contains a boolean false
var_dump(in_array(FALSE, $array, TRUE)); // FALSE
// adding a boolean with the value false to the array
$array[] = FALSE;
// checking if it contains a boolean false now
var_dump(in_array(FALSE, $array, TRUE)); // TRUE
It would return true if all values are true, otherwise false.
Returns true if array is non empty and contains no false elements:
function array_and(arary $arr)
{
return $arr && array_reduce($arr, function($a, $b) { return $a && $b; }, true));
}
(Note that you would need strict comparison if you wanted to test against the false type.)
Am I over-engineering?
Yes, because you could use:
in_array(false, $arr, true);
There's nothing wrong with this in principle, as long as you don't AND all of the values indiscriminately; that is, you should terminate as soon as the first false is found:
function array_and(array $array)
{
foreach ($array as $value)
{
if (!$value)
{
return false;
}
}
return true;
}
you should be able to implement a small function that takes an array and iterates over it checking each member to see if it is false. Return a bool from the function based on the outcome of your checking....
Easy but ugly => O(N)
$a = array(1, 2, false, 5, 6, 'a');
$_there_is_a_false = false
foreach ($a as $b) {
$_there_is_a_false = !$b ? true : $_there_is_a_false;
}
another option: array-filter
Why not just use array_product()
$set = array(1,1,1,1,0,0);
$result = array_product($set);
Output: 0
AND Logical is essentially a multiplier.
1 * 1 = 1
1 * 0 = 0
0 * 1 = 0
0 * 0 = 0
Related
Can somebody explain, what is 1 and -1 in this code: ($a>$b)?1:-1; ?
I know the Array ( [c] => blue ) is returning because the key c is not exist in $a2 and key_compare_func need to return number smaller, equal or bigger then 0.
But I don't understand, how I get the Array ( [c] => blue ), when the key_compare_func returns 0, 1 and -1:
function myfunction($a,$b) {
if ($a === $b) {
return 0;
}
return ($a > $b) ? 1 : -1;
}
$a1=array("a"=>"red","b"=>"green","c"=>"blue");
$a2=array("a"=>"blue","b"=>"black","e"=>"blue");
$result=array_diff_ukey($a1,$a2,"myfunction");
As you can see in array-diff-ukey documentation the "key_compare_func" need to return number smaller, equal or bigger then 0. the numbers 1 and -1 are just example for this results.
In your case you can simply use strcmp as it return the same logic.
You have Array ( [c] => blue ) in the return because the key c is not exist in the $a2 array as it say:
Compares the keys from array1 against the keys from array2 and returns the difference. This function is like array_diff() except the comparison is done on the keys instead of the values.
Edited
Specifically in array-diff-ukey you only need the return 0 because that the way this function is decided the keys are the same so in your example you can define it as:
function myfunction($a,$b) {
if ($a === $b)
return 0;
return 1; // or -1 or 3 or -3 **just not 0**
}
Consider that as the logic behind array-diff-ukey:
array function array-diff-ukey($a1, $a2, $compareFunction) {
$arr = array(); // init empty array
foreach($a1 as $key1 => $value1) { // for each key in a1
$found = false;
foreach($a1 as $key2 => $value2) { //search for all keys in a2
if ($compareFunction($key1, $key2) == 0)
$found = true; // found a key with the same
}
if ($found === false) // add the element only if non is found
$arr[$key1] = $value1;
}
return $arr;
}
If ($a>$b) is true (right after the ?) - you return 1. else (right after the :) will return -1.
It's a short way of writing this:
if ($a>$b) {
return 1;
} else {
return -1;
}
It is the ternary operator in PHP. You can say it as shorthand If/Else. Here is an example:
/* most basic usage */
$var = 5;
$var_is_greater_than_two = ($var > 2 ? true : false); // if $var greater than 2
// return true
// else false
If it is being difficult for you to understand, you can change it with:
if ($a===$b)
{
return 0;
}
else if($a > $b)
{
return 1;
}
else
{
return -1;
}
I have an array in which I push true or false values. And I only want to execute the next function if the array is completely true or completely. But because they are not strings, I can not check it with in_array(...).
Does anybody know how I can check if an array is completely true or completely?
Greetings and Thank You! :D
$res = array_unique($array);
if(count($res) === 1 && $res[0]) {
// your code
}
First, check if all the array have same value
Then check if it's TRUE or false.
if(count(array_count_values($array))===1){
if($array[0]){
// Completely TRUE;
}else{
// Completely FALSE;
}
}
For PHP >= 7.4
To check if all items are true:
... = array_reduce($array, fn ($carry, $item) => $carry && $carry === $item, true);
To check if all items are false:
... = array_reduce($array, fn ($carry, $item) => $carry && $carry !== $item, true);
I have an array with boolean values, e.g.
$myarray = array(true, false, false, true, false);
Now I want to perform some logic operations on my array values, so I get the output:
FALSE
from my array.
You're trying to treat booleans as strings, which is fundamentally wrong. What you want is, for example, an array reduction:
$res = array_reduce($myarray, function ($a, $b) { return $a && $b; }, true);
// default value ^^^^
Or a more efficient short-circuiting all function:
function all(array $values) {
foreach ($values as $value) {
if (!$value) {
return false;
}
}
return true;
}
if (all($myarray)) ...
You could just search your array for false, and if it's present, return false, and if not return true:
$result = (array_search(false, $myarray, true) === false);
Since you edited your question, if you want it to return 0 or 1 just do:
$result = (array_search(false, $myarray, true) === false) ? 1 : 0;
You could try this:
$res = true;
foreach ($myarray as $item) $res &= $item;
echo var_dump($res);
A bit less elegant, but it should work. You'll have an integer in the end because we're using bit logic here, could be improved.
For a OR case you could do almost the same thing:
$res = true;
foreach ($myarray as $item) $res |= $item;
echo var_dump($res);
I'm writing a function named all to check all elements inside an array $arr, returning a single boolean value (based of $f return value). This is working fine passing custom functions (see the code with $gte0 been passed to all).
However sometimes one want just check that an array contains all true values: all(true, $arr) will not work becase true is passed as boolean (and true is not a function name). Does PHP have a native true() like function?
function all($f, array $arr)
{
return empty($arr) ? false : array_reduce($arr, function($v1, $v2) use ($f) {
return $f($v1) && $f($v2);
}, true);
}
$test = array(1, 6, 2);
$gte0 = function($v) { return $v >= 0; }
var_dump(all($gte0, $test)); // True
$test = array(true, true, false);
$id = function($v) { return $v; } // <-- this is what i would avoid
var_dump(all($id, $test)); // False
all(true, $test); // NOT WORKING because true is passed as boolean
all('true', $test); // NOT WORKING because true is not a function
EDIT: another way could be checking $f in all function:
$f = is_bool($f) ? ($f ? function($v) { return $v; }
: function($v) { return !$v; } ): $f;
After adding this, calling all with true is perfectly fine.
intval might do what you're looking for (especially as the array only contains integers in your example):
var_dump(all('intval', $test)); // False
However, many types to integer conversions are undefined in PHP and with float this will round towards zero, so this might not be what you want.
The more correct "function" would be the opposite of boolean true: empty, but it's not a function, so you can't use it (and invert the return value):
var_dump(!all('empty', $test)); // Does not work!
And there is no function called boolval or similar in PHP, so write it yourself if you need it ;)
Additionally your all function could be optimized. While iterating, if the current result is already FALSE, the end result will always be FALSE. And no need to call $f() n * 2 times anyway:
function all($f, array $arr)
{
$result = (bool) $arr;
foreach($arr as $v) if (!$f($v)) return FALSE;
return $result;
}
Edit: knittl is right pointing to array_filter, it converts to boolean with no function given which seems cool as there is no "boolval" function:
function all($f, array $arr)
{
return ($c = count($arr))
&& ($f ? $arr = array_map($f, $arr) : 1)
&& $c === count(array_filter($arr));
}
var_dump(all(0, $test)); // False
Making the first function parameter optional will do you a proper bool cast on each array element thanks to array_filter.
Better to pass in a function to map the values to booleans that you can then reduce to a final value.
function all($map, $data) {
if (empty($data)) { return false; }
$reduce = function($f, $n) {
return $f && $n;
};
return array_reduce(array_map($map, $data), $reduce, true);
}
$gte0 = function($v) { return $v >= 0; };
$gte2 = function($v) { return $v >= 2; };
$data = array(1, 2, 3, 4, 5);
var_dump(all($gte0, $data));
var_dump(all($gte2, $data));
Then the result of the function remains expectant but the test can be slotted in as needed. You can go a step further and allow both the map and reduce function to be passed in.
function mr($map, $reduce, $data) {
return array_reduce(array_map($map, $data), $reduce, true);
}
You could use PHP's array_filter function, it will remove all 'falsy' values from an array if no callback is specified:
$a = array ( true, true, false );
var_dump($a == array_filter($a));
There isn't any true() function in PHP, you should compare the value to true.
try
return ($f === $v1) && ($f === $v2);
instead of
return $f($v1) && $f($v2);
I think this should work:
function all($f, array $arr)
{
return empty($arr) ? false : array_reduce($arr, function($v1, $v2) use ($f) {
return $f($v1) && $f($v2);
}, true);
}
function isTrue($a)
{
return true === $a;
}
all("isTrue", $test);
I have an array
$data = array( 'a'=>'0', 'b'=>'0', 'c'=>'0', 'd'=>'0' );
I want to check if all array values are zero.
if( all array values are '0' ) {
echo "Got it";
} else {
echo "No";
}
Thanks
I suppose you could use array_filter() to get an array of all items that are non-zero ; and use empty() on that resulting array, to determine if it's empty or not.
For example, with your example array :
$data = array(
'a'=>'0',
'b'=>'0',
'c'=>'0',
'd'=>'0' );
Using the following portion of code :
$tmp = array_filter($data);
var_dump($tmp);
Would show you an empty array, containing no non-zero element :
array(0) {
}
And using something like this :
if (empty($tmp)) {
echo "All zeros!";
}
Would get you the following output :
All zeros!
On the other hand, with the following array :
$data = array(
'a'=>'0',
'b'=>'1',
'c'=>'0',
'd'=>'0' );
The $tmp array would contain :
array(1) {
["b"]=>
string(1) "1"
}
And, as such, would not be empty.
Note that not passing a callback as second parameter to array_filter() will work because (quoting) :
If no callback is supplied, all entries of input equal to FALSE (see
converting to boolean) will be removed.
How about:
// ditch the last argument to array_keys if you don't need strict equality
$allZeroes = count( $data ) == count( array_keys( $data, '0', true ) );
Use this:
$all_zero = true;
foreach($data as $value)
if($value != '0')
{
$all_zero = false;
break;
}
if($all_zero)
echo "Got it";
else
echo "No";
This is much faster (run time) than using array_filter as suggested in other answer.
you can loop the array and exit on the first non-zero value (loops until non-zero, so pretty fast, when a non-zero value is at the beginning of the array):
function allZeroes($arr) {
foreach($arr as $v) { if($v != 0) return false; }
return true;
}
or, use array_sum (loops complete array once):
function allZeroes($arr) {
return array_sum($arr) == 0;
}
#fireeyedboy had a very good point about summing: if negative values are involved, the result may very well be zero, even though the array consists of non-zero values
Another way:
if(array_fill(0,count($data),'0') === array_values($data)){
echo "All zeros";
}
Another quick solution might be:
if (intval(emplode('',$array))) {
// at least one non zero array item found
} else {
// all zeros
}
if (!array_filter($data)) {
// empty (all values are 0, NULL or FALSE)
}
else {
// not empty
}
I'm a bit late to the party, but how about this:
$testdata = array_flip($data);
if(count($testdata) == 1 and !empty($testdata[0])){
// must be all zeros
}
A similar trick uses array_unique().
You can use this function
function all_zeros($array){//true if all elements are zeros
$flag = true;
foreach($array as $a){
if($a != 0)
$flag = false;
}
return $flag;
}
You can use this one-liner: (Demo)
var_export(!(int)implode($array));
$array = [0, 0, 0, 0]; returns true
$array = [0, 0, 1, 0]; returns false
This is likely to perform very well because there is only one function call.
My solution uses no glue when imploding, then explicitly casts the generated string as an integer, then uses negation to evaluate 0 as true and non-zero as false. (Ordinarily, 0 evaluates as false and all other values evaluate to true.)
...but if I was doing this for work, I'd probably just use !array_filter($array)