PHP - array_search() fails on === true, but not on !== false? - php

When I want to check if something is in the array and get the key back, I use the array_search() function.
Why is it when I compare the function to be exactly equal to true (=== true) it returns false, and when I compare it to not be exactly equal to false (!== false) it returns true?
<?php
if(array_search($value, $array) === true)
{
// Fails
}
if(array_search($value, $array) !== false)
{
// Succeeds
}
?>
Thanks in advance.

array_search returns you needle when a match is found. it returns false only when match is not found. This is why only the opposite works in your case.
Returns the key for needle if it is found in the array, FALSE
otherwise.

Late to the party, but wanted to add some context / examples:
array_search will return the key (if the value is found) - which could be 0 - and will return FALSE if the value is not found. It never returns TRUE.
This code may sum it up better:
// test array...
$array = [
0 => 'First Item',
1 => 'Second Item',
'x' => 'Associative Item'
];
// example results:
$key = array_search( 'First Item', $array ); // returns 0
$key = array_search( 'Second Item', $array ); // returns 1
$key = array_search( 'Associative Item', $array ); // returns 'x'
$key = array_search( 'Third Item', $array ); // returns FALSE
Since 0 is a falsey value, you wouldn't want to do something like if ( ! array_search(...) ) {... because it would fail on 0 index items.
Therefore, the way to use it is something like:
$key = array_search( 'Third Item', $array ); // returns FALSE
if ( FALSE !== $key ) {
// item was found, key is in $index, do something here...
}
It's worth mentioning this is also true of functions like strpos and stripos, so it's a good pattern to get in the habit of following.

It will fail because if the call is succesfull it returns the key no true.
false is returned if it isnt found so === false is ok
from the manual:
Returns the key for needle if it is found in the array, FALSE otherwise.

array_search() does not return true.
If will only return false, if it can't find anything, otherwise it will return the key of the matched element.
According to the manual
array_search — Searches the array for a given value and returns the corresponding key if successful
....
Returns the key for needle if it is found in the array, FALSE otherwise.

Related

Store numeric zero in an array [duplicate]

I want to remove NULL, FALSE and '' values .
I used array_filter but it removes the 0' s also.
Is there any function to do what I want?
array(NULL,FALSE,'',0,1) -> array(0,1)
array_filter should work fine if you use the identical comparison operator.
here's an example
$values = [NULL, FALSE, '', 0, 1];
function myFilter($var){
return ($var !== NULL && $var !== FALSE && $var !== '');
}
$res = array_filter($values, 'myFilter');
Or if you don't want to define a filtering function, you can also use an anonymous function (closure):
$res = array_filter($values, function($value) {
return ($value !== null && $value !== false && $value !== '');
});
If you just need the numeric values you can use is_numeric as your callback: example
$res = array_filter($values, 'is_numeric');
From http://php.net/manual/en/function.array-filter.php#111091 :
If you want to remove NULL, FALSE and Empty Strings, but leave values of 0, you can use strlen as the callback function:
array_filter($array, 'strlen');
array_filter doesn't work because, by default, it removes anything that is equivalent to FALSE, and PHP considers 0 to be equivalent to false. The PHP manual has this to say on the subject:
When converting to boolean, the following values are considered FALSE:
the boolean FALSE itself
the integer 0 (zero)
the float 0.0 (zero)
the empty string, and the string "0"
an array with zero elements
an object with zero member variables (PHP 4 only)
the special type NULL (including unset variables)
SimpleXML objects created from empty tags
Every other value is considered TRUE (including any resource).
You can pass a second parameter to array_filter with a callback to a function you write yourself, which tells array_filter whether or not to remove the item.
Assuming you want to remove all FALSE-equivalent values except zeroes, this is an easy function to write:
function RemoveFalseButNotZero($value) {
return ($value || is_numeric($value));
}
Then you just overwrite the original array with the filtered array:
$array = array_filter($array, "RemoveFalseButNotZero");
Use a custom callback function with array_filter. See this example, lifted from PHP manual, on how to use call back functions. The callback function in the example is filtering based on odd/even; you can write a little function to filter based on your requirements.
<?php
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));
}
$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);
echo "Odd :\n";
print_r(array_filter($array1, "odd"));
echo "Even:\n";
print_r(array_filter($array2, "even"));
?>
One-liners are always nice.
$clean_array = array_diff(array_map('trim', $my_array), array('', NULL, FALSE));
Explanation:
1st parameter of array_diff: The trimmed version of $my_array. Using array_map, surrounding whitespace is trimmed from every element via the trim function. It is good to use the trimmed version in case an element contains a string that is nothing but whitespace (i.e. tabs, spaces), which I assume would also want to be removed. You could just as easily use $my_array for the 1st parameter if you don't want to trim the elements.
2nd parameter of array_diff: An array of items that you would like to remove from $my_array.
Output: An array of elements that are contained in the 1st array that are not also contained in the 2nd array. In this case, because '', NULL, and FALSE are within the 2nd array, they can never be returned by array_diff.
EDIT:
It turns out you don't need to have NULL and FALSE in the 2nd array. Instead you can just have '', and it will work the same way:
$clean_array = array_diff(array_map('trim', $my_array), array(''));
function my_filter($var)
{
// returns values that are neither false nor null (but can be 0)
return ($var !== false && $var !== null && $var !== '');
}
$entry = array(
0 => 'foo',
1 => false,
2 => -1,
3 => null,
4 => '',
5 => 0
);
print_r(array_filter($entry, 'my_filter'));
Outputs:
Array
(
[0] => foo
[2] => -1
[5] => 0
)
check whether it is less than 1 and greater than -1 if then dont remove it...
$arrayValue = (NULL,FALSE,'',0,1);
$newArray = array();
foreach($arrayValue as $value) {
if(is_int($value) || ($value>-1 && $value <1)) {
$newArray[] = $value;
}
}
print_r($newArray);
Alternatively you can use array_filter with the 'strlen' parameter:
// removes all NULL, FALSE and Empty Strings but leaves 0 (zero) values
$result = array_filter($array, 'strlen');
https://www.php.net/manual/en/function.array-filter.php#111091
function ExtArray($linksArray){
foreach ($linksArray as $key => $link)
{
if ($linksArray[$key] == '' || $linksArray[$key] == NULL || $linksArray[$key] == FALSE || $linksArray[$key] == '')
{
unset($linksArray[$key]);
}else {
return $linksArray[$key];
}
}
}
This function may help you

PHP How to get a boolean average of an array

EDIT2: This goes to the top for a reason. This question is asked wrong, but I won´t change the title, since maybe other people are caught in this misstake. I am NOT looking for an "average" - I merely want to exit with the first "false" in an array.
My though to this questions were quite twisted - therefore I asked the wrong question.
Anyway: As stated, I won´t change the question itself.
What I want to do is basically calculate something like a boolean average of an array. I know about booleans and that they are not meant to be something with an average, but please read on to see what I am doing.
My array looks like this:
$array = array(
true,
false,
true,
true
);
I now want to get an AND-operation done on this array to see, if everything in there is true or if a subfunction returned false. This is basically a list of results from different subfunctions.
This specific example then should return false, because $array[1] is false.
EDIT:
What I am looking for is a builtin PHP-function which seems not to exists. A custom implementation has the advantage to exit the iteration over this array in comparison to in_array() which might not do this.
Can you help me out, stackoverflow?
Try in_array:
$array = array(
true,
false,
true,
true
);
echo in_array(false, $array);
If one of the elements is false, it will return false otherwise it returns true.
Update: in_array, returns out of the loop as soon as the searched value is matched. The worst case I suppose is when you have a single false at the end of the searched array. The linked source are for PHP 5.3.
As far as strict checking is concerned, you can do so passing in the third parameter to in_array:
echo in_array(false, $array, true);
Come on, it would appear you didn't even try:
function checkArray(array $in)
{
foreach ($in as $bool)
{
if (!$bool)//replace with type&value checking if that's what you're after
return false;
}
return true;
}
var_dump(checkArray(array(true, false, true, true)));//false
var_dump(checkArray(array(true, true)));//true
There are, of course, a bunch of alternative ways to do what you want/need, depending on what the actual data will look like. If it's all booleans:
if (array_sum($array) != count($array))
{//true == 1, array_sum(array(true, true)) == count(array(true, true)) == 2
echo 'array contains false, or non-boolean values, like 123';
}
//for a real average:
$avg = round(array_sum($array)/count($array));
The latter will yield 1 if 50%>= of the values in the array are true, and 0 otherwise. It's then a simple matter of casting that value to a boolean to get the "average bool value":
$avg = (bool) round(
array_sum($array)/count($array)
);
or, for example:
$valsAsKey = array_flip(
array_map(
'intval',//make ints
$array
)
);
if (isset($valsAsKey[0]))
{//(int) false === 0
echo 'False in array';
}
Though these approaches don't use iteration explicitly, they do iterate the array data implicitly. A quick test did show that the simple foreach outperformed the other approaches here.
I have tried around a lot, until i came to this final result.
This is my code:
<?php
$array = array();
$array[] = true;
$array[] = false;
$array[] = false;
$array[] = true;
$array[] = false;
var_dump($array);
if((count($array)/2) <= array_sum($array)){
echo "true";
// return true
} else {
echo "false";
// return false
}
?>
it counts the elements of the array, and compares it with the COUNTED trues (array_sum($array)). Then it returns true or false, dependent on result.
You could iterate through the array and set a result to false if any vals are false;
$result = true;
foreach ($array as $v) {
if ($v===false) $result = false;
}
You can use array_filter without callback. In this case all entries of array equal to false will be removed.
if (count(array_filter($array)) == count($array)) echo 'TRUE';

array_search and destroy logic error

I am trying to search an array and see if a value is contained in it. If the value is in the array then the index of the value in the array will be passed onto be removed from the array.
The problem is array_search returns FALSE if the value is not found, but since false is a boolean it is also treated as 0. When this is passed to the unset to remove the value from the array the value at index 0 will be removed if array_search returned false.
I am fairly sure it will need to be put into an if statement but how will I handle the response if both an integer and a boolean can both be returned?
Current Code:
$pos = array_search($value, $array);
unset($array[$pos]);
PHP Doc says..
This function may return Boolean FALSE, but may also return a
non-Boolean value which evaluates to FALSE. Please read the section on
Booleans for more information. Use the === operator for testing the
return value of this function.
So you need to do like this
<?php
$arr = [1,2,3];
$pos = array_search(4, $arr);
if($pos!==false)
{
unset($arr[$pos]);
}
print_r($arr);
OUTPUT
Array
(
[0] => 1
[1] => 2
[2] => 3
)
As you can see the first index is retained.
try this
if($pos !== false)
{
// do your work to unset
}
note !== in above code
$x !== $y is True if $x is not equal to $y, or they are not of the same type
You can try this script, hope this will help you...
if(in_array($value, $array)){
$pos = array_search($value, $array);
unset($array[$pos]);
}

PHP Count Number of True Values in a Boolean Array

I have an associative array in which I need to count the number of boolean true values within.
The end result is to create an if statement in which would return true when only one true value exists within the array. It would need to return false if there are more then one true values within the array, or if there are no true values within the array.
I know the best route would be to use count and in_array in some form. I'm not sure this would work, just off the top of my head but even if it does, is this the best way?
$array(a->true,b->false,c->true)
if (count(in_array(true,$array,true)) == 1)
{
return true
}
else
{
return false
}
I would use array_filter.
$array = array(true, true, false, false);
echo count(array_filter($array));
//outputs: 2
Array_filter will remove values that are false-y (value == false). Then just get a count. If you need to filter based on some special value, like if you are looking for a specific value, array_filter accepts an optional second parameter that is a function you can define to return whether a value is true (not filtered) or false (filtered out).
Since TRUE is casted to 1 and FALSE is casted to 0. You can also use array_sum
$array = array('a'=>true,'b'=>false,'c'=>true);
if(array_sum($array) == 1) {
//one and only one true in the array
}
From the doc : "FALSE will yield 0 (zero), and TRUE will yield 1 (one)."
Try this approach :
<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>
Result :
Array
(
[1] => 2
[hello] => 2
[world] => 1
)
Documentation
like this?
$trues = 0;
foreach((array)$array as $arr) {
$trues += ($arr ? 1 : 0);
}
return ($trues==1);
Have you tried using array_count_values to get an array with everything counted? Then check how many true's there are?

PHP's variable type leniency

The most recent comment on PHP's in_array() help page (http://uk.php.net/manual/en/function.in-array.php#106319) states that some unusual results occur as a result of PHP's 'leniency on variable types', but gives no explanation as to why these results occur. In particular, I don't follow why these happen:
// Example array
$array = array(
'egg' => true,
'cheese' => false,
'hair' => 765,
'goblins' => null,
'ogres' => 'no ogres allowed in this array'
);
// Loose checking (this is the default, i.e. 3rd argument is false), return values are in comments
in_array(763, $array); // true
in_array('hhh', $array); // true
Or why the poster thought the following was strange behaviour
in_array('egg', $array); // true
in_array(array(), $array); // true
(surely 'egg' does occur in the array, and PHP doesn't care whether it's a key or value, and there is an array, and PHP doesn't care if it's empty or not?)
Can anyone give any pointers?
763 == true because true equals anything not 0, NULL or '', same thing for array because it is a value (not an object).
To circumvent this problem you should pass the third argument as TRUE to be STRICT and thus, is_rray will do a === which is a type equality so then
763 !== true
and neither will array() !== true
Internally, you can think of the basic in_array() call working like this:
function in_array($needle, $haystack, $strict = FALSE) {
foreach ($haystack as $key => $value) {
if ($strict === FALSE) {
if ($value == $needle) {
return($key);
}
} else {
if ($value === $needle) {
return($key);
}
}
return(FALSE);
}
note that it's using the == comparison operator - this one allows typecasting. So if your array contains a simple boolean TRUE value, then essentially EVERYTHING your search for with in_array will be found, and almost everything EXCEPT the following in PHP can be typecast as true:
'' == TRUE // false
0 == TRUE // false
FALSE == TRUE // false
array() == TRUE // false
'0' == TRUE // false
but:
'a' == TRUE // true
1 == TRUE // true
'1' == TRUE // true
3.1415926 = TRUE // true
etc...
This is why in_array has the optional 3rd parameter to force a strict comparison. It simply makes in_array do a === strict comparison, instead of ==.
Which means that
'a' === TRUE // FALSE
PHP treating arrays as primitive values is a constant source of pain as they can be very complex data structures, it doesn't make any sense. For example, if you assign array to something, and then modify the array, the original isn't modified, instead it is copied.
<?php
$arr = array(
"key" => NULL
);
var_dump( array() == NULL ); //True :(
var_dump( in_array( array(), $arr ) ); //True, wtf? It's because apparently array() == NULL
var_dump( in_array( new stdClass, $arr ) ); //False, thank god
?>
Also, 'egg' is not a value in the array, it's a key, so of course it's surprising that it would return true. This kind of behavior is not ok in any other language I know about, so it will trip over many people who don't know php quirks inside out.
Even a simple rule that an empty string is falsy, is violated in php:
if( "0" ) {
echo "hello"; //not executed
}
"0" is a non-empty string by any conceivable definition, yet it is a falsy value.

Categories