array_search can't find element which is clearly there - php

Why does the following code work:
$test = array(0=>'test1','field0'=>'test2',1=>'test3','field1'=>'test4');
echo array_search('test4',$test);
But the following doesn't:
$test = array(0=>0,'field0'=>'test2',1=>'test3','field1'=>'test4');
echo array_search('test4',$test);
If you had a mixed array from say mysql_fetch_array($result,MYSQL_BOTH) and took the keys which you needed to search you wouldn't be able too - it would never progress further than 0.

Try to do array_search('test4',$test, TRUE);. The 3rd parameter tells it to use === instead of == when comparing.
Since your array holds both strings and numbers, when it compares to the 0 (the 1st element), it converts 'test4' to a number (it stops at the 1st non-numeric character) and it happens to match.
What I mean is: 'test4' == 0 => 0 == 0 => true.
When you pass TRUE as the 3rd parameter, it uses ===, and 'test4' === 0 is automatically false since the types don't match, there is no conversion.

The solution = force the 0 value to be a string:
$test = array(0=>0,'field0'=>'test2',1=>'test3','field1'=>'test4');
foreach ($test as $k=>$v){ $test[$k] = (string) $v; }
echo array_search('test4',$test);

You can't search a number for a string and expect a good result.
My guess is it sees the value as a number, so it converts your string to a number (which it can't) so that string gets converted to a 0. So the value of 0 equals the search string, which also equals 0, and there's your result.
If the value is 1, it won't match as the search string gets converted to a 0 (as you can't convert a string to a number) so it wouldn't match in the following.
$test = array(0=>1,'field0'=>'test2',1=>'test3','field1'=>'test4');
You'll only get your exact case scenario when that value in the array is 0.

Related

Php, in_array, 0 value

I was trying to understand the in_array behavior at the next scenario:
$arr = array(2 => 'Bye', 52, 77, 3 => 'Hey');
var_dump(in_array(0, $arr));
The returned value of the in_array() is boolean true. As you can see there is no value equal to 0, so if can some one please help me understand why does the function return true?
This is a known issue, per the comments in the documentation. Consider the following examples:
in_array(0, array(42)); // FALSE
in_array(0, array('42')); // FALSE
in_array(0, array('Foo')); // TRUE
To avoid this, provide the third paramter, true, placing the comparison in strict mode which will not only compare values, but types as well:
var_dump(in_array(0, $arr, true));
Other work-arounds exist that don't necessitate every check being placed in strict-mode:
in_array($value, $my_array, empty($value) && $value !== '0');
But Why?
The reason behind all of this is likely string-to-number conversions. If we attempt to get a number from "Bye", we are given 0, which is the value we're asking to look-up.
echo intval("Bye"); // 0
To confirm this, we can use array_search to find the key that is associated with the matching value:
$arr = array(2 => 'Bye', 52, 77, 3 => 'Hey');
echo array_search(0, $arr);
In this, the returned key is 2, meaning 0 is being found in the conversion of Bye to an integer.
Try adding a third parameter true (strict mode) to your in_array call.
This is a result of the loose comparison and type juggling.
Loose comparison means that PHP is using == not === when comparing elements. == does not compare that the two variable types are equal, only their value, while === will ensure that they match in type and value (e.g. compare 0 == FALSE and 0 === FALSE).
So, basically, your in_array function is checking:
0 == 'Bye'
0 == 'Hey'
0 == 77
Note that the 52 will get lost due to the way you created your array.
So, note that if you do:
print (0 == 'Bye');
You will get 1. Apparently, PHP is type juggling the 'Bye' to 0, which is the same thing that will happen when you cast a string to an int, e.g. (int) 'string' will equal 0. Specific reference from the String conversion to numbers doc (Emphasis added):
The value is given by the initial portion of the string. If the string
starts with valid numeric data, this will be the value used.
Otherwise, the value will be 0 (zero). Valid numeric data is an
optional sign, followed by one or more digits (optionally containing a
decimal point), followed by an optional exponent. The exponent is an
'e' or 'E' followed by one or more digits.
Apparently, the integer type takes precedence over the string type (i.e. it could just as easily be doing the comparison by casting the int 0 to a string, which would then return False). This is specified in the comparison operators doc:
If you compare a number with a string or the comparison involves
numerical strings, then each string is converted to a number and the
comparison performed numerically.
Thanks for an interesting question that led me to do some research and learn something new!
in_array is supposed to be used on indexed arrays ([0], [1], [2] etc), not with a dictionary as you have defined (key-value store).
If you want to check if your array $arr includes '0', try using the PHP function array_key_exists instead - http://php.net/manual/en/function.array-key-exists.php.
var_dump(array_key_exists(0, $arr));
Type compare (third parameter) needs more system resources and more time.
Simply do that:
$x=0;
$result=in_array($x.'',array('ABC','BAC','12c','54'));
var_dump($result);

Difference Between $a = 0 and $a = '0' in PHP

I had an if statement similar to the following in my code and it took me forever to figure out what the problem was.
$a = 0;
if($a == 'something')
{
//this was being output when I didn't want it to be
}
Using
$a = '0';
fixed it, but I don't really know what's going on here.
One's a string, one's an integer. PHP will translate between the two as needed, unless you're using the 'strict' operators:
(0 == '0') // true
(0 === '0') // false (types don't match).
In your case, you'r comparing an integer 0 to a string 'something'. PHP will convert the string 'something' to an integer. If there's no digits in there at all, it'll conver to an integer 0, which makes your comparison true.
Just a guess, but I assume it's trying to cast the string to an integer.
intval('something') I expect will return 0.
You were comparing a numeric value ($a = 0;) to a string. In this case the string is casted to number, and PHP cast strings to 0 if there is no number in the beginning, so is true.
In the other case however you campared two strings, which are different, so it is false.

Foreach loop issues in php

Here is some code I have: (p just echos plus adds a newline)
foreach ($vanSteps as $k => $reqInfo)
{
p($k);
if ('van' == $k) { p('The key is the van, continue'); continue; }//continue if we reached the part of the array where van is key
//do stuff
}
and I'm getting this output:
0
The key is the van, continue
1
2
3
van
The key is the van, continue
Why does the if statement return true when the key is 0? This foreach loop handles logic that applies when the key == 0 (and any other key except if the key is 'van') and this messes up the logic because it's return true when key is 0.
Any help?
Thank you.
Use === for this comparison. When PHP compares string and integer it first casts string to integer value and then does comparison.
See Comparison Operators in manual.
In PHP 'van' == 0 is true. This is because when using == to compare a string and a number, the string is converted to a number (as described in the second link below); this makes the comparison internally become 0 == 0 which is of course true.
The suggested alternative for your needs, would be to use a strict equality comparison using ===.
See Comparison Operators and String conversion to numbers
In PHP, when you compare 2 types, it has to convert them to the same type. In your case, you compare string with int.
Internally this gets converted to
if((int)'van'==0)....
and then
if((int)'van'==1)....
(int)'any possible string' will be 0:) So you either have to manually convert the both values to the same type, or use === as a comparison operator, instead of the loose =.
An exception from this rule(as pointed out in the comments) would be if the string start with a number, or can be interpreted as a number in any way(1, 0002, -1 etc). In this case, the string would be interpreted as a number, diregarding the end of the non-numeric end-of-string
Take a look at http://php.net/manual/en/types.comparisons.php for more details.
This works fine:
$array = array(0=>"a",1=>"b","van"=>"booya!");
function p($v){ echo "{$v}<br />"; }
foreach ($array as $k => $reqInfo)
{
p($k);
if ('van' === $k) { p('The key is the van, continue'); continue; }//continue if we reached the part of the array where van is key
//do stuff
}
Output:
0
1
van
The key is the van, continue
Note the ===.
Read the Comparison with Various Types table
When one of the operand is number, the other operand is converted to number too. Since 'van' is non-numeric sting, it's converted to 0. You should use === operator in the case, which also checks the variable type
That's becuase 'van' == 0 (true).
Instead, you should use 'van' === 0 (false).
In short, use === instead of ==.
Its interpreting the 'van' as a boolean value (false) which 0 is equal to.
To check for exact matches in type and value in PHP you must use === instead of ==

Why the value being equalled to string in php

It is in this way:
$arr_val = array(0,1,'0','1');
foreach ($arr_val as $key){
echo ($key == "TEST")?"EQUALLED":"NOT EQUALLED"."<br>";
}
0 == "TEST" prints "EQUALLED"
1 == "TEST" prints "NOT EQUALLED"
'0' =="TEST" prints "NOT EQUALLED"
'1' =="TEST" prints "NOT EQUALLED"
When I say it prints the value "SELECTED". But why the above first case prints equalled. Any ideas on this please? How would this be equal to. We know the fix to do comparision with
(===) operator. But I am trying to know the reason why (0=="TEST") is true.
When you provide PHP's == operator with a mixture of numeric and string operands, PHP will attempt to convert the string to the matching numeric type, part of a process it calls "type juggling". In this case, the string "TEST" converts to integer 0 so your test is equivalent to 0 == 0 which is true.
PHP provides the === operator, for testing if the value and type of both operands are equal. So while 0 == "TEST" will evaulate to true, 0 === "TEST" will not, and neither will 0 === "0" or 0 === 0.0.
Note that when PHP converts a string to a number, it attempts to parse the string for a valid number. See intval for more information on how it does this. Had you'd written 0 == "1TEST", the expression would have evaulated to 0 == 1, or false.
In your second example, 1 == "TEST", the string "TEST" is again converted to an integer resulting in 1 == 0, which is false.
Your last two examples use string comparisons. There is no conversion involved, and the results are self-explanatory.
PHP provides a comprehensive breakdown of how variables of different type compare for equality.
Because 0 is an integer, behind the scenes, this is the comparison that happens:
0 == intval( "TEST" )

PHP: Check if 0?

I am using a class which returns me the value of a particular row and cell of an excel spreadsheet. To build up an array of one column I am counting the rows and then looping through that number with a for() loop and then using the $array[] = $value to set the incrementing array object's value.
This works great if none of the values in a cell are 0. The class returns me a number 0 so it's nothing to do with the class, I think it's the way I am looping through the rows and then assigning them to the array... I want to carry through the 0 value because I am creating graphs with the data afterwards, here is the code I have.
// Get Rainfall
$rainfall = array();
for($i=1;$i<=$count;$i++)
{
if($data->val($i,2) != 'Rainfall') // Check if not the column title
{
$rainfall[] = $data->val($i,2);
}
}
For your info $data is the excel spreadsheet object and the method $data->val(row,col) is what returns me the value. In this case I am getting data from column 2.
Screenshot of spreadsheet
Did you try an array_push() ?
array_push($rainfall, $data->val($i,2));
I would use a strict comparison with the not identical operator here instead of using the not equals operator:
if($data->val($i,2) !== 'Rainfall')
If $data->val($i,2) is an integer and you use == both sides will be cast to integers which would give you the result that all integers would work as you expect except for zero. Here's a summary of the difference between == and === when comparing the string "RainFall" with zero:
0 == "RainFall" : true
0 != "RainFall" : false
0 === "RainFall" : false
0 !== "RainFall" : true
I think that the array is treating the 0 like false, which could explain it not going into the array. Would something like this work (if you are using integers)?
(int)($data->val($i,2));
or
(float)($data->val($i,2);)
The problem lies in the if statement. You're trying to compare a string with an integer, which according to the PHP documentation will typecast both to integers.
If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically. These rules also apply to the switch statement. The type conversion does not take place when the comparison is === or !== as this involves comparing the type as well as the value.
You can read more here http://php.net/manual/en/language.operators.comparison.php.
Update: The if statement won't work in the case of 0 because (int)"Rainfall" will by typecasted into 0 by PHP causing the statement to be if (0 != 0) { ... }.
If $i represents the row number, why don't you start from 2 instead of 1?

Categories