Why count(false) return 1? - php

Do you know why <?= count(false) ?> returns 1?

It's specified behavior:
If var is not an array or an object with implemented Countable
interface, 1 will be returned.
According to http://php.net/manual/en/function.count.php

Because false is also a value and if the count() does not get array but a valid variable it returns true which is 1.
$result = count(null);
// $result == 0
$result = count(false);
// $result == 1

A nice way to remember this in your mind:
count(false) is basically the same as:
count ("one boolean"), and therefore there are "ONE" booleans as result.

It looks to me like PHP is preventing one from using count() to determine if an element is an array or an object. They have dedicated functions for this (is_array(), is_object()) and it may be tempting to naively use count() and check for a false condition to determine array or object. Instead, PHP makes non-objects, non-arrays return 1 (which is truthy) so that this method cannot be be naively used in this way (since 0 is a valid, falsy result for an empty array/object).
This may be the why behind the choice of value to be returned by the function in the situation you're describing.

Related

whats the difference between $a = (true === !!array_intersect(['1'],[3,2,1])); and checking with in_array

When to use this:-
$a = (true === !!array_intersect(['1'], [3, 2, 1]));
and when to use this
$b = in_array('1', [3,2,1]);
Both returns same.
array_intersect() returns the common elements form both array. In your code array_intersect(['1'], [3,2,1]) the returns [1] and when use !! then it's value is true. Because:
![1] is false
Again !false gets true
Finally (true === !!array_intersect(['1'], [3,2,1])) return true, because both sites are true. Note: === is used to check strictly (with type). That means the value of $a is true.
Second part of code:
in_array() is used to check weather an element is exist or not in an array. In your code in_array('1',[3,2,1]); is true because 1 is exist in array [3, 2, 1]
The difference between array_intersect() and in_array() are:
array_intersect($arr1, $arr2) return an array which are common in both array $arr1 and $arr2
in_array($elm, $arr) returns a Boolean (true or false) based on the existence of $elm in the array $arr
Since both parts of your code are getting logically true, that's why you are getting the same value true.
in_array is much more readable compared to the array_intersect version of the same. However, array_intersect is much faster compared to in_array. So to answer your question, use array_intersect only if you are dealing with a data set large enough to raise performance issues. Otherwise sticking to in_array will make life easier for the next developer. Cheers
Both are different things.
array_intersect Compare the values of two arrays, and return the matches:
$a1=array(0=>"red",1=>"green",2=>"blue",3=>"yellow");
$a2=array(0=>"red",1=>"green",2=>"blue");
$result=array_intersect($a1,$a2);
print_r($result);
Output will be
Array ( [0] => red [1] => green [2] => blue )
in_array is for check if the value exists or not.
$a1=array(0=>"red",1=>"green",2=>"blue",3=>"yellow");
in_array('red',$a); //true
in_array('black',$a); //false
Now, If you want to check the value is exists in an array then you may use in_array it'll return true or false, Or if you want get matches value from two array then you may use array_intersect.
It's not quite the same though. From the docs:
Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.
So, when using array_intersect(), you will always get true, but only because the string representation of your second array element "1" matches that of the array you intersect it with. With in_array(), you can have a third argument, strict, which is a boolean to indicate whether to also use type checking (see here). So, in your second example, you also have the option of checking whether the type matches, which is more fine-grained.
Personally, I would use the second option in any case just for its readability.
If you want to find elements in an array and get a subarray, then you should go for array_intersect() for performance reasons see accepted answer to this post

in_array function returns true when passing empty array

I noticed the following strange occurrence:
var_dump(in_array("test", array_keys(array("hello"))));
Yields: bool(true)
How is this possible? Array does not contains keys, therefore array_keys() will return an empty array. Test is not in this empty array, so why would it return true? Is this a bug in PHP?
simple answer: loose typing, 'test' == 0
Use
var_dump(in_array("test", array_keys(array("hello")), true));
for strict typing
And all arrays have keys, if you don't explicitly assign a key, then PHP will assign one based on incrementing integers from 0 (hence 'test' == 0).... array_keys() will not be empty, because PHP will assign a key of 0 to your array entry of "hello"

Testing an array for an empty string and returning an int (0 or 1) - best practice

What I started with:
foreach($a as $b){if($b=='')return 0;}return 1; // works but verbose
My second attempt:
return (in_array('',$a)+0); // returns the opposite of what I need
What I am currently using:
return in_array('',$a)?'0':'1';
using a cast per JRL (shortest)
return (int)!in_array('',$a);
I assume this is the best way to do this, but just wanted to validate. Is this the best way to test for an empty value in an array?
I am aware that this tests for 0,NULL,FALSE or an empty string and that is O.K.
Here's a modification of your second statement that should work. Just negate the return value of in_array:
return !in_array('',$a);
Other alternative:
return (int)!in_array('', $a));
Your proposal to check an array $a for strings cannot be written shorter than:
return in_array('', $a)?0:1;
If you want to see the difference between 0, NULL, FALSE, or an empty string, add a third parameter to the in_array function. This parameter will force the function to also take the type of the element into account. In other words, it compares using === instead of ==.
return in_array('', $a, TRUE)?0:1; //Empty string
return in_array(0, $a, TRUE)?0:1; //Zero
return in_array(NULL, $a, TRUE)?0:1; //NULL
return in_array(FALSE, $a, TRUE)?0:1;//FALSE
See also: http://www.php.net/manual/en/function.in-array.php
First one isn't correct.
Second one isn't correct
Third one is perfect for your case
OT: Trying to codegolf?
I think as far as best practice goes, just plain !in_array('', $a) is the way to go.
There's (generally speaking) no good reason to cast it to an int. Type juggling in PHP works very well. It isn't the PHP way to do casts like this.

Is there an easier way to understand negation of a function result?

I recently had to write a piece of code where I used the following; but it was very confusing for me and took me longer than I should
I keep getting lost by the negation and false turning into true and then back maybe. I end up solving these problems by trial and error.
Here is the code for getting rid of empty elements. NB, perhaps there are better code but I'm interested in knowing how to think this through
array_filter($array, "eliminate");
function eliminate($v)
{
return !(empty($v));
}
array_filter takes two arguments. The first is an array. The second is a callback. Here you are using the name of a function contained within a string "eliminate" to tell PHP which function you want to invoke.
The purpose of array_filter is to remove items from the array if you don't want them. The function from the second argument is called on every item in the array. The item is passed as the first argument to that function -- so $v in your above code is set to the value of the element we're looking at. If you return true from your callback, the item is kept in the array. If you return false, it is removed.
Your function returns true or false based on the following:
return !(empty($v));
empty returns true if the element is empty (e.g. an empty string, an empty array, the integer 0, among others). The ! operator turns this around. So the function will return false (and remove the item from the array) if the item is empty. Otherwise, it will return true and keep it.
Your function is approximately equivalent to the following loop:
$newArray = array();
foreach ($oldArray as $key=>$value) {
if (!empty($value)) {
$newArray[$key] = $value;
}
}
Iterates over each value in the input array passing them to the callback function. If the
callback function returns true, the current value from input is returned into the result array.
Array keys are preserved.
Source: http://php.net/array_filter
Each element is passed to eliminate function. Now inside eliminate if the value passed is empty it will return false and it will not belong in the next array.
Please note that your code does nothing because you should do:
$newArray=array_filter($array, "eliminate"); //< note the newarray
function eliminate($v)
{
return !(empty($v));
}
Or a better code with PHP 5.3
$newArray=array_filter($array, function ($v){
return !(empty($v));
} );
The best way to think about this code is by "talking" it out:
Let's start with eliminate, eliminate returns true when $v is not empty, false otherwise
Now, array_filter applies the designated function, here it's eliminate, to every element in $array, one at a time.
Finally, we need to understand that if, for some single element $v in $array, eliminate($v) returns true, then that element is removed.
array_filter runs the callback function on each array element. If the callback returns true, the element is kept, if false it's removed.
So, for every element in $array, it checks if it's empty(). If it's not, it gets to stay in the array, if it is it leaves. empty() returns true if it's empty (which means we want it removed from the array), so we need to return false.
If you call array_filter without a callback, it remove things that convert to false, so in your case $array = array_filter($array); should work.
array_filter returns you the modified array.
Just use:
array_filter($array);
This will eliminate every empty element of the array - the result should be identical to the code you have shown (with 'eliminate' function and !(empty($v)) code).

How to check if an array has an element at the specified index?

I know there is array_key_exists() but after reading the documentation I'm not really sure if it fits for this case:
I have an $array and an $index. Now I want to access the $array, but don't know if it has an index matching $index. I'm not talking about an associative array, but an plain boring normal numerically indexed array.
Is there an safe way to figure out if I would really access an $array element with the given $index (which is an integer!)?
PHP may not care if I access an array with an index out of bounds and maybe just returns NULL or so, but I don't want to even attempt to code dirty, so I want to check if the array has the key, or not ;-)
You can use either the language construct isset, or the function array_key_exists : numeric or string key doesn't matter : it's still an associative array, for PHP.
isset should be a bit faster (as it's not a function), but will return false if the element exists and has the value NULL.
For example, considering this array :
$a = array(
123 => 'glop',
456 => null,
);
And those three tests, relying on isset :
var_dump(isset($a[123]));
var_dump(isset($a[456]));
var_dump(isset($a[789]));
You'll get this kind of output :
boolean true
boolean false
boolean false
Because :
in the first case, the element exists, and is not null
in the second, the element exists, but is null
and, in the third, the element doesn't exist
On the other hand, using array_key_exists like in this portion of code :
var_dump(array_key_exists(123, $a));
var_dump(array_key_exists(456, $a));
var_dump(array_key_exists(789, $a));
You'll get this output :
boolean true
boolean true
boolean false
Because :
in the two first cases, the element exists -- even if it's null in the second case
and, in the third, it doesn't exist.
You can easily use isset():
if (isset($array[$index])) {
// array index $index exists
}
And as you have suggested, PHP is not very kind if you try to access a non-existent index, so it is crucial that you check that you are within bounds when dealing with accessing specific array indexes.
If you decide to use array_key_exists(), please note that there is a subtle difference:
isset() does not return TRUE for array
keys that correspond to a NULL value,
while array_key_exists() does.
That's exactly what the array_key_exists is for. It works on both numerical and string indexes.

Categories